Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of html; | 5 part of html; |
| 6 | 6 |
| 7 class _Property { | 7 class _Property { |
| 8 _Property(this.name) : | 8 _Property(this.name) |
| 9 _hasValue = false, | 9 : _hasValue = false, |
| 10 writable = false, | 10 writable = false, |
| 11 isMethod = false, | 11 isMethod = false, |
| 12 isOwn = true, | 12 isOwn = true, |
| 13 wasThrown = false; | 13 wasThrown = false; |
| 14 | 14 |
| 15 bool get hasValue => _hasValue; | 15 bool get hasValue => _hasValue; |
| 16 get value => _value; | 16 get value => _value; |
| 17 set value(v) { | 17 set value(v) { |
| 18 _value = v; | 18 _value = v; |
| 19 _hasValue = true; | 19 _hasValue = true; |
| 20 } | 20 } |
| 21 | 21 |
| 22 final String name; | 22 final String name; |
| 23 Function setter; | 23 Function setter; |
| 24 Function getter; | 24 Function getter; |
| 25 var _value; | 25 var _value; |
| 26 bool _hasValue; | 26 bool _hasValue; |
| 27 bool writable; | 27 bool writable; |
| 28 bool isMethod; | 28 bool isMethod; |
| 29 bool isOwn; | 29 bool isOwn; |
| 30 bool wasThrown; | 30 bool wasThrown; |
| 31 } | 31 } |
| 32 | 32 |
| 33 /** | |
| 34 * Manager for navigating between libraries from the devtools console. | |
| 35 */ | |
| 36 class _LibraryManager { | |
| 37 /** | |
| 38 * Current active library | |
| 39 */ | |
| 40 static var _currentLibrary; | |
| 41 static var _validCache = false; | |
| 42 | |
| 43 static Map<String, Uri> _libraryUris; | |
| 44 static Map<String, Uri> _libraryNames; | |
| 45 | |
| 46 // List of all maps to check to determine if there is an exact match. | |
| 47 static List<Map<String, Uri>> _fastPaths; | |
| 48 | |
| 49 static cache() { | |
| 50 if (_validCache) return; | |
| 51 _validCache = true; | |
| 52 _libraryUris = new Map<String, Uri>(); | |
| 53 _libraryNames = new Map<String, Uri>(); | |
| 54 _fastPaths = [_libraryUris, _libraryNames]; | |
| 55 var system = currentMirrorSystem(); | |
| 56 system.libraries.forEach((uri, library) { | |
| 57 _libraryUris[uri.toString()] = uri; | |
|
Alan Knight
2016/04/06 20:07:27
What happens if multiple libraries have the same s
Jacob
2016/04/07 00:09:25
cleaned this code up. Now that case is properly ha
| |
| 58 _libraryNames[MirrorSystem.getName(library.simpleName)] = uri; | |
| 59 }); | |
| 60 } | |
| 61 | |
| 62 static String get currentLibrary { | |
| 63 if (_currentLibrary == null) { | |
| 64 _currentLibrary = | |
| 65 currentMirrorSystem().isolate.rootLibrary.uri.toString(); | |
| 66 } | |
| 67 return _currentLibrary; | |
| 68 } | |
| 69 | |
| 70 /** | |
| 71 * Find libraries matching a given name. | |
| 72 * | |
| 73 * Uses heuristics to only return a single match when the user intent is | |
| 74 * generally unambiguous. | |
| 75 */ | |
| 76 static List<Uri> findMatches(String name) { | |
| 77 cache(); | |
| 78 var nameAsFile = name.endsWith('.dart') ? name : '${name}.dart'; | |
| 79 | |
| 80 // Perfect match first. | |
| 81 for (var map in _fastPaths) { | |
|
Alan Knight
2016/04/06 20:07:28
In the spirit of heuristics for what the user want
Jacob
2016/04/07 00:09:25
Done. Added a case insensitive check as a final fa
| |
| 82 var match = map[name]; | |
| 83 if (match != null) return [match]; | |
| 84 match = map[nameAsFile]; | |
| 85 if (match != null) return [match]; | |
| 86 } | |
| 87 | |
| 88 // Exact match for file path. | |
| 89 var matches = new LinkedHashSet<Uri>(); | |
| 90 for (var uri in _libraryUris.values) { | |
| 91 if (uri.path == name || uri.path == nameAsFile) matches.add(uri); | |
| 92 } | |
| 93 if (matches.length == 1) return matches.toList(); | |
| 94 | |
| 95 // Exact match for file name. | |
| 96 if (name != nameAsFile) { | |
| 97 for (var uri in _libraryUris.values) { | |
| 98 if (uri.pathSegments.isNotEmpty && | |
| 99 (uri.pathSegments.last == nameAsFile)) { | |
| 100 matches.add(uri); | |
| 101 } | |
| 102 } | |
| 103 if (matches.length == 1) return matches.toList(); | |
| 104 } | |
| 105 | |
| 106 for (var uri in _libraryUris.values) { | |
| 107 if (uri.pathSegments.isNotEmpty && (uri.pathSegments.last == name)) { | |
| 108 matches.add(uri); | |
| 109 } | |
| 110 } | |
| 111 if (matches.length == 1) return matches.toList(); | |
| 112 | |
| 113 // Partial match on path. | |
| 114 for (var uri in _libraryUris.values) { | |
| 115 if (uri.path.contains(name)) { | |
| 116 matches.add(uri); | |
| 117 } | |
| 118 } | |
| 119 if (matches.length == 1) return matches.toList(); | |
| 120 | |
| 121 // Partial match on entire uri. | |
| 122 for (var uri in _libraryUris.values) { | |
| 123 if (uri.toString().contains(name)) { | |
| 124 matches.add(uri); | |
| 125 } | |
| 126 } | |
| 127 return matches.toList(); | |
| 128 } | |
| 129 | |
| 130 static setLibrary([String name]) { | |
| 131 // Bust cache in case library list has changed. Ideally we would listen for | |
| 132 // when libraries are loaded and invalidate based on that. | |
| 133 _validCache = false; | |
| 134 cache(); | |
| 135 if (name == null) { | |
| 136 window.console | |
| 137 ..group("Current library: $_currentLibrary") | |
| 138 ..groupCollapsed("All libraries:"); | |
| 139 _listLibraries(); | |
| 140 window.console..groupEnd()..groupEnd(); | |
| 141 return; | |
| 142 } | |
| 143 var matches = findMatches(name); | |
| 144 if (matches.length != 1) { | |
| 145 if (matches.length > 1) { | |
| 146 window.console.warn("Ambiguous library name."); | |
|
Alan Knight
2016/04/06 20:07:27
Say what the ambiguous name is?
Jacob
2016/04/07 00:09:25
Done.
| |
| 147 } | |
| 148 showMatches(name, matches); | |
| 149 return; | |
| 150 } | |
| 151 _currentLibrary = matches.first.toString(); | |
| 152 window.console.log("Set library to $_currentLibrary"); | |
| 153 } | |
| 154 | |
| 155 static getLibrary() { | |
| 156 return currentLibrary; | |
| 157 } | |
| 158 | |
| 159 static List<Uri> _sortUris(Iterable<Uri> uris) { | |
| 160 return (uris.toList()) | |
| 161 ..sort((Uri a, Uri b) { | |
| 162 if (a.scheme != b.scheme) { | |
| 163 if (a.scheme == 'dart') return -1; | |
| 164 if (b.scheme == 'dart') return 1; | |
| 165 return a.scheme.compareTo(b.scheme); | |
| 166 } | |
| 167 return a.toString().compareTo(b.toString()); | |
| 168 }); | |
| 169 } | |
| 170 | |
| 171 static void listLibraries() { | |
| 172 _validCache = false; | |
| 173 cache(); | |
| 174 _listLibraries(); | |
| 175 } | |
| 176 | |
| 177 static void _listLibraries() { | |
| 178 window.console.log(_sortUris(_libraryUris.values).join("\n")); | |
| 179 } | |
| 180 | |
| 181 // Workaround to allow calling console.log with an arbitrary number of | |
| 182 // arguments. | |
| 183 static void _log(List<String> args) { | |
| 184 js.JsNative.callMethod(window.console, 'log', args); | |
| 185 } | |
| 186 | |
| 187 static showMatches(String key, Iterable<Uri> uris) { | |
| 188 var boldPairs = []; | |
| 189 var sb = new StringBuffer(); | |
| 190 if (uris.isEmpty) { | |
| 191 window.console.group("All libraries:"); | |
| 192 _listLibraries(); | |
| 193 window.console | |
| 194 ..groupEnd() | |
| 195 ..error("No library names or URIs match '$key'"); | |
| 196 return; | |
| 197 } | |
| 198 sb.write("${uris.length} matches\n"); | |
| 199 for (var uri in uris) { | |
| 200 var txt = uri.toString(); | |
| 201 int index = txt.indexOf(key); | |
| 202 if (index != -1) { | |
| 203 // %c enables styling console log messages with css | |
| 204 // specified at the end of the console. | |
| 205 sb..write(txt.substring(0, index))..write('%c'); | |
| 206 var matchEnd = index + key.length; | |
| 207 sb | |
| 208 ..write(txt.substring(index, matchEnd)) | |
| 209 ..write('%c') | |
| 210 ..write(txt.substring(matchEnd)) | |
| 211 ..write('\n'); | |
| 212 boldPairs..add('font-weight: bold')..add('font-weight: normal'); | |
| 213 } | |
| 214 } | |
| 215 _log([sb.toString()]..addAll(boldPairs)); | |
| 216 } | |
| 217 } | |
| 218 | |
| 33 class _ConsoleVariables { | 219 class _ConsoleVariables { |
| 34 Map<String, Object> _data = new Map<String, Object>(); | 220 Map<String, Object> _data = new Map<String, Object>(); |
| 35 | 221 |
| 36 /** | 222 /** |
| 37 * Forward member accesses to the backing JavaScript object. | 223 * Forward member accesses to the backing JavaScript object. |
| 38 */ | 224 */ |
| 39 noSuchMethod(Invocation invocation) { | 225 noSuchMethod(Invocation invocation) { |
| 40 String member = MirrorSystem.getName(invocation.memberName); | 226 String member = MirrorSystem.getName(invocation.memberName); |
| 41 if (invocation.isGetter) { | 227 if (invocation.isGetter) { |
| 42 return _data[member]; | 228 return _data[member]; |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 68 */ | 254 */ |
| 69 abstract class _Trampoline implements Function { | 255 abstract class _Trampoline implements Function { |
| 70 final ObjectMirror _receiver; | 256 final ObjectMirror _receiver; |
| 71 final MethodMirror _methodMirror; | 257 final MethodMirror _methodMirror; |
| 72 final Symbol _selector; | 258 final Symbol _selector; |
| 73 | 259 |
| 74 _Trampoline(this._receiver, this._methodMirror, this._selector); | 260 _Trampoline(this._receiver, this._methodMirror, this._selector); |
| 75 } | 261 } |
| 76 | 262 |
| 77 class _MethodTrampoline extends _Trampoline { | 263 class _MethodTrampoline extends _Trampoline { |
| 78 _MethodTrampoline(ObjectMirror receiver, MethodMirror methodMirror, | 264 _MethodTrampoline( |
| 79 Symbol selector) : | 265 ObjectMirror receiver, MethodMirror methodMirror, Symbol selector) |
| 80 super(receiver, methodMirror, selector); | 266 : super(receiver, methodMirror, selector); |
| 81 | 267 |
| 82 noSuchMethod(Invocation msg) { | 268 noSuchMethod(Invocation msg) { |
| 83 if (msg.memberName != #call) return super.noSuchMethod(msg); | 269 if (msg.memberName != #call) return super.noSuchMethod(msg); |
| 84 return _receiver.invoke(_selector, | 270 return _receiver |
| 85 msg.positionalArguments, | 271 .invoke(_selector, msg.positionalArguments, msg.namedArguments) |
| 86 msg.namedArguments).reflectee; | 272 .reflectee; |
| 87 } | 273 } |
| 88 } | 274 } |
| 89 | 275 |
| 90 /** | 276 /** |
| 91 * Invocation trampoline class used to closurize getters. | 277 * Invocation trampoline class used to closurize getters. |
| 92 */ | 278 */ |
| 93 class _GetterTrampoline extends _Trampoline { | 279 class _GetterTrampoline extends _Trampoline { |
| 94 _GetterTrampoline(ObjectMirror receiver, MethodMirror methodMirror, | 280 _GetterTrampoline( |
| 95 Symbol selector) : | 281 ObjectMirror receiver, MethodMirror methodMirror, Symbol selector) |
| 96 super(receiver, methodMirror, selector); | 282 : super(receiver, methodMirror, selector); |
| 97 | 283 |
| 98 call() => _receiver.getField(_selector).reflectee; | 284 call() => _receiver.getField(_selector).reflectee; |
| 99 } | 285 } |
| 100 | 286 |
| 101 /** | 287 /** |
| 102 * Invocation trampoline class used to closurize setters. | 288 * Invocation trampoline class used to closurize setters. |
| 103 */ | 289 */ |
| 104 class _SetterTrampoline extends _Trampoline { | 290 class _SetterTrampoline extends _Trampoline { |
| 105 _SetterTrampoline(ObjectMirror receiver, MethodMirror methodMirror, | 291 _SetterTrampoline( |
| 106 Symbol selector) : | 292 ObjectMirror receiver, MethodMirror methodMirror, Symbol selector) |
| 107 super(receiver, methodMirror, selector); | 293 : super(receiver, methodMirror, selector); |
| 108 | 294 |
| 109 call(value) { | 295 call(value) { |
| 110 _receiver.setField(_selector, value); | 296 _receiver.setField(_selector, value); |
| 111 } | 297 } |
| 112 } | 298 } |
| 113 | 299 |
| 114 class _Utils { | 300 class _Utils { |
| 115 static double dateTimeToDouble(DateTime dateTime) => | 301 static double dateTimeToDouble(DateTime dateTime) => |
| 116 dateTime.millisecondsSinceEpoch.toDouble(); | 302 dateTime.millisecondsSinceEpoch.toDouble(); |
| 117 static DateTime doubleToDateTime(double dateTime) { | 303 static DateTime doubleToDateTime(double dateTime) { |
| 118 try { | 304 try { |
| 119 return new DateTime.fromMillisecondsSinceEpoch(dateTime.toInt()); | 305 return new DateTime.fromMillisecondsSinceEpoch(dateTime.toInt()); |
| 120 } catch(_) { | 306 } catch (_) { |
| 121 // TODO(antonnm): treat exceptions properly in bindings and | 307 // TODO(antonnm): treat exceptions properly in bindings and |
| 122 // find out how to treat NaNs. | 308 // find out how to treat NaNs. |
| 123 return null; | 309 return null; |
| 124 } | 310 } |
| 125 } | 311 } |
| 126 | 312 |
| 127 static List convertToList(List list) { | 313 static List convertToList(List list) { |
| 128 // FIXME: [possible optimization]: do not copy the array if Dart_IsArray is fine w/ it. | 314 // FIXME: [possible optimization]: do not copy the array if Dart_IsArray is fine w/ it. |
| 129 final length = list.length; | 315 final length = list.length; |
| 130 List result = new List(length); | 316 List result = new List(length); |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 155 result[list[i]] = list[i + 1]; | 341 result[list[i]] = list[i + 1]; |
| 156 } | 342 } |
| 157 } | 343 } |
| 158 | 344 |
| 159 static bool isMap(obj) => obj is Map; | 345 static bool isMap(obj) => obj is Map; |
| 160 | 346 |
| 161 static List toListIfIterable(obj) => obj is Iterable ? obj.toList() : null; | 347 static List toListIfIterable(obj) => obj is Iterable ? obj.toList() : null; |
| 162 | 348 |
| 163 static Map createMap() => {}; | 349 static Map createMap() => {}; |
| 164 | 350 |
| 165 static parseJson(String jsonSource) => const JsonDecoder().convert(jsonSource) ; | 351 static parseJson(String jsonSource) => |
| 352 const JsonDecoder().convert(jsonSource); | |
| 353 | |
| 354 static String getLibraryUrl() => _LibraryManager.currentLibrary; | |
| 166 | 355 |
| 167 static makeUnimplementedError(String fileName, int lineNo) { | 356 static makeUnimplementedError(String fileName, int lineNo) { |
| 168 return new UnsupportedError('[info: $fileName:$lineNo]'); | 357 return new UnsupportedError('[info: $fileName:$lineNo]'); |
| 169 } | 358 } |
| 170 | 359 |
| 171 static bool isTypeSubclassOf(Type type, Type other) { | 360 static bool isTypeSubclassOf(Type type, Type other) { |
| 172 if (type == other) { | 361 if (type == other) { |
| 173 return true; | 362 return true; |
| 174 } | 363 } |
| 175 var superclass = reflectClass(type).superclass; | 364 var superclass = reflectClass(type).superclass; |
| 176 if (superclass != null) { | 365 if (superclass != null) { |
| 177 return isTypeSubclassOf(superclass.reflectedType, other); | 366 return isTypeSubclassOf(superclass.reflectedType, other); |
| 178 } | 367 } |
| 179 return false; | 368 return false; |
| 180 } | 369 } |
| 181 | 370 |
| 182 static Element getAndValidateNativeType(Type type, String tagName) { | 371 static Element getAndValidateNativeType(Type type, String tagName) { |
| 183 var element = new Element.tag(tagName); | 372 var element = new Element.tag(tagName); |
| 184 if (!isTypeSubclassOf(type, element.runtimeType)) { | 373 if (!isTypeSubclassOf(type, element.runtimeType)) { |
| 185 return null; | 374 return null; |
| 186 } | 375 } |
| 187 return element; | 376 return element; |
| 188 } | 377 } |
| 189 | 378 |
| 190 static forwardingPrint(String message) => _blink.Blink_Utils.forwardingPrint(m essage); | 379 static forwardingPrint(String message) => |
| 380 _blink.Blink_Utils.forwardingPrint(message); | |
| 191 static void spawnDomHelper(Function f, int replyTo) => | 381 static void spawnDomHelper(Function f, int replyTo) => |
| 192 _blink.Blink_Utils.spawnDomHelper(f, replyTo); | 382 _blink.Blink_Utils.spawnDomHelper(f, replyTo); |
| 193 | 383 |
| 194 // TODO(vsm): Make this API compatible with spawnUri. It should also | 384 // TODO(vsm): Make this API compatible with spawnUri. It should also |
| 195 // return a Future<Isolate>. | 385 // return a Future<Isolate>. |
| 196 // TODO(jacobr): IS THIS RIGHT? I worry we have broken conversion from Promise to Future. | 386 // TODO(jacobr): IS THIS RIGHT? I worry we have broken conversion from Promise to Future. |
| 197 static spawnDomUri(String uri) => _blink.Blink_Utils.spawnDomUri(uri); | 387 static spawnDomUri(String uri) => _blink.Blink_Utils.spawnDomUri(uri); |
| 198 | 388 |
| 199 // The following methods were added for debugger integration to make working | 389 // The following methods were added for debugger integration to make working |
| 200 // with the Dart C mirrors API simpler. | 390 // with the Dart C mirrors API simpler. |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 213 | 403 |
| 214 /** | 404 /** |
| 215 * Takes a list containing variable names and corresponding values and | 405 * Takes a list containing variable names and corresponding values and |
| 216 * returns a map from normalized names to values. Variable names are assumed | 406 * returns a map from normalized names to values. Variable names are assumed |
| 217 * to have list offsets 2*n values at offset 2*n+1. This method is required | 407 * to have list offsets 2*n values at offset 2*n+1. This method is required |
| 218 * because Dart_GetLocalVariables returns a list instead of an object that | 408 * because Dart_GetLocalVariables returns a list instead of an object that |
| 219 * can be queried to lookup names and values. | 409 * can be queried to lookup names and values. |
| 220 */ | 410 */ |
| 221 static Map<String, dynamic> createLocalVariablesMap(List localVariables) { | 411 static Map<String, dynamic> createLocalVariablesMap(List localVariables) { |
| 222 var map = {}; | 412 var map = {}; |
| 223 for (int i = 0; i < localVariables.length; i+=2) { | 413 for (int i = 0; i < localVariables.length; i += 2) { |
| 224 map[stripMemberName(localVariables[i])] = localVariables[i+1]; | 414 map[stripMemberName(localVariables[i])] = localVariables[i + 1]; |
| 225 } | 415 } |
| 226 return map; | 416 return map; |
| 227 } | 417 } |
| 228 | 418 |
| 229 static _ConsoleVariables _consoleTempVariables = new _ConsoleVariables(); | 419 static _ConsoleVariables _consoleTempVariables = new _ConsoleVariables(); |
| 230 | 420 |
| 231 /** | 421 /** |
| 232 * Takes an [expression] and a list of [local] variable and returns an | 422 * Takes an [expression] and a list of [local] variable and returns an |
| 233 * expression for a closure with a body matching the original expression | 423 * expression for a closure with a body matching the original expression |
| 234 * where locals are passed in as arguments. Returns a list containing the | 424 * where locals are passed in as arguments. Returns a list containing the |
| 235 * String expression for the closure and the list of arguments that should | 425 * String expression for the closure and the list of arguments that should |
| 236 * be passed to it. The expression should then be evaluated using | 426 * be passed to it. The expression should then be evaluated using |
| 237 * Dart_EvaluateExpr which will generate a closure that should be invoked | 427 * Dart_EvaluateExpr which will generate a closure that should be invoked |
| 238 * with the list of arguments passed to this method. | 428 * with the list of arguments passed to this method. |
| 239 * | 429 * |
| 240 * For example: | 430 * For example: |
| 241 * <code> | 431 * <code> |
| 242 * _consoleTempVariables = {'a' : someValue, 'b': someOtherValue} | 432 * _consoleTempVariables = {'a' : someValue, 'b': someOtherValue} |
| 243 * wrapExpressionAsClosure("foo + bar + a", ["bar", 40, "foo", 2], true) | 433 * wrapExpressionAsClosure("foo + bar + a", ["bar", 40, "foo", 2], true) |
| 244 * </code> | 434 * </code> |
| 245 * will return: | 435 * will return: |
| 246 * <code> | 436 * <code> |
| 247 * ["""(final $consoleVariables, final bar, final foo, final a, final b) => | 437 * ["""(final $consoleVariables, final bar, final foo, final a, final b) => |
| 248 * (foo + bar + a | 438 * (foo + bar + a |
| 249 * )""", | 439 * )""", |
| 250 * [_consoleTempVariables, 40, 2, someValue, someOtherValue]] | 440 * [_consoleTempVariables, 40, 2, someValue, someOtherValue]] |
| 251 * </code> | 441 * </code> |
| 252 */ | 442 */ |
| 253 static List wrapExpressionAsClosure(String expression, List locals, | 443 static List wrapExpressionAsClosure( |
| 254 bool includeCommandLineAPI) { | 444 String expression, List locals, bool includeCommandLineAPI) { |
| 255 var args = {}; | 445 var args = {}; |
| 256 var sb = new StringBuffer("("); | 446 var sb = new StringBuffer("("); |
| 257 addArg(arg, value) { | 447 addArg(arg, value) { |
| 258 arg = stripMemberName(arg); | 448 arg = stripMemberName(arg); |
| 259 if (args.containsKey(arg)) return; | 449 if (args.containsKey(arg)) return; |
| 260 // We ignore arguments with the name 'this' rather than throwing an | 450 // We ignore arguments with the name 'this' rather than throwing an |
| 261 // exception because Dart_GetLocalVariables includes 'this' and it | 451 // exception because Dart_GetLocalVariables includes 'this' and it |
| 262 // is more convenient to filter it out here than from C++ code. | 452 // is more convenient to filter it out here than from C++ code. |
| 263 // 'this' needs to be handled by calling Dart_EvaluateExpr with | 453 // 'this' needs to be handled by calling Dart_EvaluateExpr with |
| 264 // 'this' as the target rather than by passing it as an argument. | 454 // 'this' as the target rather than by passing it as an argument. |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 279 // FIXME: use a real Dart tokenizer. The following regular expressions | 469 // FIXME: use a real Dart tokenizer. The following regular expressions |
| 280 // only allow setting variables at the immediate start of the expression | 470 // only allow setting variables at the immediate start of the expression |
| 281 // to limit the number of edge cases we have to handle. | 471 // to limit the number of edge cases we have to handle. |
| 282 | 472 |
| 283 // Match expressions that start with "var x" | 473 // Match expressions that start with "var x" |
| 284 final _VARIABLE_DECLARATION = new RegExp("^(\\s*)var\\s+(\\w+)"); | 474 final _VARIABLE_DECLARATION = new RegExp("^(\\s*)var\\s+(\\w+)"); |
| 285 // Match expressions that start with "someExistingConsoleVar =" | 475 // Match expressions that start with "someExistingConsoleVar =" |
| 286 final _SET_VARIABLE = new RegExp("^(\\s*)(\\w+)(\\s*=)"); | 476 final _SET_VARIABLE = new RegExp("^(\\s*)(\\w+)(\\s*=)"); |
| 287 // Match trailing semicolons. | 477 // Match trailing semicolons. |
| 288 final _ENDING_SEMICOLONS = new RegExp("(;\\s*)*\$"); | 478 final _ENDING_SEMICOLONS = new RegExp("(;\\s*)*\$"); |
| 289 expression = expression.replaceAllMapped(_VARIABLE_DECLARATION, | 479 expression = expression.replaceAllMapped(_VARIABLE_DECLARATION, (match) { |
| 290 (match) { | 480 var variableName = match[2]; |
| 291 var variableName = match[2]; | 481 // Set the console variable if it isn't already set. |
| 292 // Set the console variable if it isn't already set. | 482 if (!_consoleTempVariables._data.containsKey(variableName)) { |
| 293 if (!_consoleTempVariables._data.containsKey(variableName)) { | 483 _consoleTempVariables._data[variableName] = null; |
| 294 _consoleTempVariables._data[variableName] = null; | 484 } |
| 295 } | 485 return "${match[1]}\$consoleVariables.${variableName}"; |
| 296 return "${match[1]}\$consoleVariables.${variableName}"; | 486 }); |
| 297 }); | |
| 298 | 487 |
| 299 expression = expression.replaceAllMapped(_SET_VARIABLE, | 488 expression = expression.replaceAllMapped(_SET_VARIABLE, (match) { |
| 300 (match) { | 489 var variableName = match[2]; |
| 301 var variableName = match[2]; | 490 // Only rewrite if the name matches an existing console variable. |
| 302 // Only rewrite if the name matches an existing console variable. | 491 if (_consoleTempVariables._data.containsKey(variableName)) { |
| 303 if (_consoleTempVariables._data.containsKey(variableName)) { | 492 return "${match[1]}\$consoleVariables.${variableName}${match[3]}"; |
| 304 return "${match[1]}\$consoleVariables.${variableName}${match[3]}"; | 493 } else { |
| 305 } else { | 494 return match[0]; |
| 306 return match[0]; | 495 } |
| 307 } | 496 }); |
| 308 }); | |
| 309 | 497 |
| 310 // We only allow dart expressions not Dart statements. Silently remove | 498 // We only allow dart expressions not Dart statements. Silently remove |
| 311 // trailing semicolons the user might have added by accident to reduce the | 499 // trailing semicolons the user might have added by accident to reduce the |
| 312 // number of spurious compile errors. | 500 // number of spurious compile errors. |
| 313 expression = expression.replaceFirst(_ENDING_SEMICOLONS, ""); | 501 expression = expression.replaceFirst(_ENDING_SEMICOLONS, ""); |
| 314 } | 502 } |
| 315 | 503 |
| 316 if (locals != null) { | 504 if (locals != null) { |
| 317 for (int i = 0; i < locals.length; i+= 2) { | 505 for (int i = 0; i < locals.length; i += 2) { |
| 318 addArg(locals[i], locals[i+1]); | 506 addArg(locals[i], locals[i + 1]); |
| 319 } | 507 } |
| 320 } | 508 } |
| 321 // Inject all the already defined console variables. | 509 // Inject all the already defined console variables. |
| 322 _consoleTempVariables._data.forEach(addArg); | 510 _consoleTempVariables._data.forEach(addArg); |
| 323 | 511 |
| 324 // TODO(jacobr): remove the parentheses around the expresson once | 512 // TODO(jacobr): remove the parentheses around the expresson once |
| 325 // dartbug.com/13723 is fixed. Currently we wrap expression in parentheses | 513 // dartbug.com/13723 is fixed. Currently we wrap expression in parentheses |
| 326 // to ensure only valid Dart expressions are allowed. Otherwise the DartVM | 514 // to ensure only valid Dart expressions are allowed. Otherwise the DartVM |
| 327 // quietly ignores trailing Dart statements resulting in user confusion | 515 // quietly ignores trailing Dart statements resulting in user confusion |
| 328 // when part of an invalid expression they entered is ignored. | 516 // when part of an invalid expression they entered is ignored. |
| 329 sb..write(') => (\n$expression\n)'); | 517 sb..write(') => (\n$expression\n)'); |
| 330 return [sb.toString(), args.values.toList(growable: false)]; | 518 return [sb.toString(), args.values.toList(growable: false)]; |
| 331 } | 519 } |
| 332 | 520 |
| 333 static String _getShortSymbolName(Symbol symbol, | 521 static String _getShortSymbolName( |
| 334 DeclarationMirror declaration) { | 522 Symbol symbol, DeclarationMirror declaration) { |
| 335 var name = MirrorSystem.getName(symbol); | 523 var name = MirrorSystem.getName(symbol); |
| 336 if (declaration is MethodMirror) { | 524 if (declaration is MethodMirror) { |
| 337 if (declaration.isSetter && name[name.length-1] == "=") { | 525 if (declaration.isSetter && name[name.length - 1] == "=") { |
| 338 return name.substring(0, name.length-1); | 526 return name.substring(0, name.length - 1); |
| 339 } | 527 } |
| 340 if (declaration.isConstructor) { | 528 if (declaration.isConstructor) { |
| 341 return name.substring(name.indexOf('.') + 1); | 529 return name.substring(name.indexOf('.') + 1); |
| 342 } | 530 } |
| 343 } | 531 } |
| 344 return name; | 532 return name; |
| 345 } | 533 } |
| 346 | 534 |
| 347 /** | 535 /** |
| 536 * Handle special console commands such as $lib and $libs that should not be | |
|
Alan Knight
2016/04/06 20:07:27
It says $lib here, but library below. Or are these
| |
| 537 * evaluated as Dart expressions and instead should be interpreted directly. | |
| 538 * Commands supported: | |
| 539 * library <-- shows the current library and lists all libraries. | |
| 540 * library "library_uri" <-- select a specific library | |
| 541 * library "library_uri_fragment" | |
| 542 */ | |
| 543 static bool maybeHandleSpecialConsoleCommand(String expression) { | |
| 544 expression = expression.trim(); | |
| 545 var setLibraryCommand = r'library '; | |
|
Alan Knight
2016/04/06 20:07:27
Why the r'?
| |
| 546 if (expression == r'library') { | |
| 547 _LibraryManager.setLibrary(); | |
| 548 return true; | |
| 549 } | |
| 550 if (expression.startsWith(setLibraryCommand)) { | |
| 551 expression = expression.substring(setLibraryCommand.length); | |
| 552 if (expression.length >= 2) { | |
| 553 String start = expression[0]; | |
| 554 String end = expression[expression.length - 1]; | |
| 555 // TODO(jacobr): maybe we should require quotes. | |
| 556 if ((start == "'" && end == "'") || (start == '"' && end == '"')) { | |
| 557 expression = expression.substring(1, expression.length - 1); | |
| 558 } | |
| 559 } | |
| 560 | |
| 561 _LibraryManager.setLibrary(expression); | |
| 562 return true; | |
| 563 } | |
| 564 return false; | |
| 565 } | |
| 566 | |
| 567 /** | |
| 348 * Returns a list of completions to use if the receiver is o. | 568 * Returns a list of completions to use if the receiver is o. |
| 349 */ | 569 */ |
| 350 static List<String> getCompletions(o) { | 570 static List<String> getCompletions(o) { |
| 351 MirrorSystem system = currentMirrorSystem(); | 571 MirrorSystem system = currentMirrorSystem(); |
| 352 var completions = new Set<String>(); | 572 var completions = new Set<String>(); |
| 353 addAll(Map<Symbol, dynamic> map, bool isStatic) { | 573 addAll(Map<Symbol, dynamic> map, bool isStatic) { |
| 354 map.forEach((symbol, mirror) { | 574 map.forEach((symbol, mirror) { |
| 355 if (mirror.isStatic == isStatic && !mirror.isPrivate) { | 575 if (mirror.isStatic == isStatic && !mirror.isPrivate) { |
| 356 var name = MirrorSystem.getName(symbol); | 576 var name = MirrorSystem.getName(symbol); |
| 357 if (mirror is MethodMirror && mirror.isSetter) | 577 if (mirror is MethodMirror && mirror.isSetter) name = |
| 358 name = name.substring(0, name.length - 1); | 578 name.substring(0, name.length - 1); |
| 359 completions.add(name); | 579 completions.add(name); |
| 360 } | 580 } |
| 361 }); | 581 }); |
| 362 } | 582 } |
| 363 | 583 |
| 364 addForClass(ClassMirror mirror, bool isStatic) { | 584 addForClass(ClassMirror mirror, bool isStatic) { |
| 365 if (mirror == null) | 585 if (mirror == null) return; |
| 366 return; | |
| 367 addAll(mirror.declarations, isStatic); | 586 addAll(mirror.declarations, isStatic); |
| 368 if (mirror.superclass != null) | 587 if (mirror.superclass != null) addForClass(mirror.superclass, isStatic); |
| 369 addForClass(mirror.superclass, isStatic); | |
| 370 for (var interface in mirror.superinterfaces) { | 588 for (var interface in mirror.superinterfaces) { |
| 371 addForClass(interface, isStatic); | 589 addForClass(interface, isStatic); |
| 372 } | 590 } |
| 373 } | 591 } |
| 374 | 592 |
| 375 if (o is Type) { | 593 if (o is Type) { |
| 376 addForClass(reflectClass(o), true); | 594 addForClass(reflectClass(o), true); |
| 377 } else { | 595 } else { |
| 378 addForClass(reflect(o).type, false); | 596 addForClass(reflect(o).type, false); |
| 379 } | 597 } |
| 380 return completions.toList(growable: false); | 598 return completions.toList(growable: false); |
| 381 } | 599 } |
| 382 | 600 |
| 383 /** | 601 /** |
| 384 * Adds all candidate String completitions from [declarations] to [output] | 602 * Adds all candidate String completitions from [declarations] to [output] |
| 385 * filtering based on [staticContext] and [includePrivate]. | 603 * filtering based on [staticContext] and [includePrivate]. |
| 386 */ | 604 */ |
| 387 static void _getCompletionsHelper(ClassMirror classMirror, | 605 static void _getCompletionsHelper(ClassMirror classMirror, bool staticContext, |
| 388 bool staticContext, LibraryMirror libraryMirror, Set<String> output) { | 606 LibraryMirror libraryMirror, Set<String> output) { |
| 389 bool includePrivate = libraryMirror == classMirror.owner; | 607 bool includePrivate = libraryMirror == classMirror.owner; |
| 390 classMirror.declarations.forEach((symbol, declaration) { | 608 classMirror.declarations.forEach((symbol, declaration) { |
| 391 if (!includePrivate && declaration.isPrivate) return; | 609 if (!includePrivate && declaration.isPrivate) return; |
| 392 if (declaration is VariableMirror) { | 610 if (declaration is VariableMirror) { |
| 393 if (staticContext != declaration.isStatic) return; | 611 if (staticContext != declaration.isStatic) return; |
| 394 } else if (declaration is MethodMirror) { | 612 } else if (declaration is MethodMirror) { |
| 395 if (declaration.isOperator) return; | 613 if (declaration.isOperator) return; |
| 396 if (declaration.isConstructor) { | 614 if (declaration.isConstructor) { |
| 397 if (!staticContext) return; | 615 if (!staticContext) return; |
| 398 var name = MirrorSystem.getName(declaration.constructorName); | 616 var name = MirrorSystem.getName(declaration.constructorName); |
| 399 if (name.isNotEmpty) output.add(name); | 617 if (name.isNotEmpty) output.add(name); |
| 400 return; | 618 return; |
| 401 } | 619 } |
| 402 if (staticContext != declaration.isStatic) return; | 620 if (staticContext != declaration.isStatic) return; |
| 403 } else if (declaration is TypeMirror) { | 621 } else if (declaration is TypeMirror) { |
| 404 return; | 622 return; |
| 405 } | 623 } |
| 406 output.add(_getShortSymbolName(symbol, declaration)); | 624 output.add(_getShortSymbolName(symbol, declaration)); |
| 407 }); | 625 }); |
| 408 | 626 |
| 409 if (!staticContext) { | 627 if (!staticContext) { |
| 410 for (var interface in classMirror.superinterfaces) { | 628 for (var interface in classMirror.superinterfaces) { |
| 411 _getCompletionsHelper(interface, staticContext, | 629 _getCompletionsHelper(interface, staticContext, libraryMirror, output); |
| 412 libraryMirror, output); | |
| 413 } | 630 } |
| 414 if (classMirror.superclass != null) { | 631 if (classMirror.superclass != null) { |
| 415 _getCompletionsHelper(classMirror.superclass, staticContext, | 632 _getCompletionsHelper( |
| 416 libraryMirror, output); | 633 classMirror.superclass, staticContext, libraryMirror, output); |
| 417 } | 634 } |
| 418 } | 635 } |
| 419 } | 636 } |
| 420 | 637 |
| 421 static void _getLibraryCompletionsHelper( | 638 static void _getLibraryCompletionsHelper( |
| 422 LibraryMirror library, bool includePrivate, Set<String> output) { | 639 LibraryMirror library, bool includePrivate, Set<String> output) { |
| 423 library.declarations.forEach((symbol, declaration) { | 640 library.declarations.forEach((symbol, declaration) { |
| 424 if (!includePrivate && declaration.isPrivate) return; | 641 if (!includePrivate && declaration.isPrivate) return; |
| 425 output.add(_getShortSymbolName(symbol, declaration)); | 642 output.add(_getShortSymbolName(symbol, declaration)); |
| 426 }); | 643 }); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 473 _getLibraryCompletionsHelper(dependency.targetLibrary, false, names); | 690 _getLibraryCompletionsHelper(dependency.targetLibrary, false, names); |
| 474 } else { | 691 } else { |
| 475 names.add(MirrorSystem.getName(dependency.prefix)); | 692 names.add(MirrorSystem.getName(dependency.prefix)); |
| 476 } | 693 } |
| 477 } | 694 } |
| 478 } | 695 } |
| 479 return names.toList(); | 696 return names.toList(); |
| 480 } | 697 } |
| 481 | 698 |
| 482 static final SIDE_EFFECT_FREE_LIBRARIES = new Set<String>() | 699 static final SIDE_EFFECT_FREE_LIBRARIES = new Set<String>() |
| 483 ..add('dart:html') | 700 ..add('dart:html') |
| 484 ..add('dart:indexed_db') | 701 ..add('dart:indexed_db') |
| 485 ..add('dart:svg') | 702 ..add('dart:svg') |
| 486 ..add('dart:typed_data') | 703 ..add('dart:typed_data') |
| 487 ..add('dart:web_audio') | 704 ..add('dart:web_audio') |
| 488 ..add('dart:web_gl') | 705 ..add('dart:web_gl') |
| 489 ..add('dart:web_sql'); | 706 ..add('dart:web_sql'); |
| 490 | 707 |
| 491 static LibraryMirror _getLibrary(MethodMirror methodMirror) { | 708 static LibraryMirror _getLibrary(MethodMirror methodMirror) { |
| 492 var owner = methodMirror.owner; | 709 var owner = methodMirror.owner; |
| 493 if (owner is ClassMirror) { | 710 if (owner is ClassMirror) { |
| 494 return owner; | 711 return owner; |
| 495 } else if (owner is LibraryMirror) { | 712 } else if (owner is LibraryMirror) { |
| 496 return owner; | 713 return owner; |
| 497 } | 714 } |
| 498 return null; | 715 return null; |
| 499 } | 716 } |
| 500 | 717 |
| 501 /** | 718 /** |
| 502 * For parity with the JavaScript debugger, we treat some getters as if | 719 * For parity with the JavaScript debugger, we treat some getters as if |
| 503 * they are fields so that users can see their values immediately. | 720 * they are fields so that users can see their values immediately. |
| 504 * This matches JavaScript's behavior for getters on DOM objects. | 721 * This matches JavaScript's behavior for getters on DOM objects. |
| 505 * In the future we should consider adding an annotation to tag getters | 722 * In the future we should consider adding an annotation to tag getters |
| 506 * in user libraries as side effect free. | 723 * in user libraries as side effect free. |
| 507 */ | 724 */ |
| 508 static bool _isSideEffectFreeGetter(MethodMirror methodMirror, | 725 static bool _isSideEffectFreeGetter( |
| 509 LibraryMirror libraryMirror) { | 726 MethodMirror methodMirror, LibraryMirror libraryMirror) { |
| 510 // This matches JavaScript behavior. We should consider displaying | 727 // This matches JavaScript behavior. We should consider displaying |
| 511 // getters for all dart platform libraries rather than just the DOM | 728 // getters for all dart platform libraries rather than just the DOM |
| 512 // libraries. | 729 // libraries. |
| 513 return libraryMirror.uri.scheme == 'dart' && | 730 return libraryMirror.uri.scheme == 'dart' && |
| 514 SIDE_EFFECT_FREE_LIBRARIES.contains(libraryMirror.uri.toString()); | 731 SIDE_EFFECT_FREE_LIBRARIES.contains(libraryMirror.uri.toString()); |
| 515 } | 732 } |
| 516 | 733 |
| 517 /** | 734 /** |
| 518 * Whether we should treat a property as a field for the purposes of the | 735 * Whether we should treat a property as a field for the purposes of the |
| 519 * debugger. | 736 * debugger. |
| 520 */ | 737 */ |
| 521 static bool treatPropertyAsField(MethodMirror methodMirror, | 738 static bool treatPropertyAsField( |
| 522 LibraryMirror libraryMirror) { | 739 MethodMirror methodMirror, LibraryMirror libraryMirror) { |
| 523 return (methodMirror.isGetter || methodMirror.isSetter) && | 740 return (methodMirror.isGetter || methodMirror.isSetter) && |
| 524 (methodMirror.isSynthetic || | 741 (methodMirror.isSynthetic || |
| 525 _isSideEffectFreeGetter(methodMirror,libraryMirror)); | 742 _isSideEffectFreeGetter(methodMirror, libraryMirror)); |
| 526 } | 743 } |
| 527 | 744 |
| 528 // TODO(jacobr): generate more concise function descriptions instead of | 745 // TODO(jacobr): generate more concise function descriptions instead of |
| 529 // dumping the entire function source. | 746 // dumping the entire function source. |
| 530 static String describeFunction(function) { | 747 static String describeFunction(function) { |
| 531 if (function is _Trampoline) return function._methodMirror.source; | 748 if (function is _Trampoline) return function._methodMirror.source; |
| 532 try { | 749 try { |
| 533 var mirror = reflect(function); | 750 var mirror = reflect(function); |
| 534 return mirror.function.source; | 751 return mirror.function.source; |
| 535 } catch (e) { | 752 } catch (e) { |
| 536 return function.toString(); | 753 return function.toString(); |
| 537 } | 754 } |
| 538 } | 755 } |
| 539 | 756 |
| 540 static List getInvocationTrampolineDetails(_Trampoline method) { | 757 static List getInvocationTrampolineDetails(_Trampoline method) { |
| 541 var loc = method._methodMirror.location; | 758 var loc = method._methodMirror.location; |
| 542 return [loc.line, loc.column, loc.sourceUri.toString(), | 759 return [ |
| 543 MirrorSystem.getName(method._selector)]; | 760 loc.line, |
| 761 loc.column, | |
| 762 loc.sourceUri.toString(), | |
| 763 MirrorSystem.getName(method._selector) | |
| 764 ]; | |
| 544 } | 765 } |
| 545 | 766 |
| 546 static List getLibraryProperties(String libraryUrl, bool ownProperties, | 767 static List getLibraryProperties( |
| 547 bool accessorPropertiesOnly) { | 768 String libraryUrl, bool ownProperties, bool accessorPropertiesOnly) { |
| 548 var properties = new Map<String, _Property>(); | 769 var properties = new Map<String, _Property>(); |
| 549 var libraryMirror = getLibraryMirror(libraryUrl); | 770 var libraryMirror = getLibraryMirror(libraryUrl); |
| 550 _addInstanceMirrors(libraryMirror, libraryMirror, | 771 _addInstanceMirrors( |
| 772 libraryMirror, | |
| 773 libraryMirror, | |
| 551 libraryMirror.declarations, | 774 libraryMirror.declarations, |
| 552 ownProperties, accessorPropertiesOnly, false, false, | 775 ownProperties, |
| 776 accessorPropertiesOnly, | |
| 777 false, | |
| 778 false, | |
| 553 properties); | 779 properties); |
| 554 if (!accessorPropertiesOnly) { | 780 if (!accessorPropertiesOnly) { |
| 555 // We need to add class properties for all classes in the library. | 781 // We need to add class properties for all classes in the library. |
| 556 libraryMirror.declarations.forEach((symbol, declarationMirror) { | 782 libraryMirror.declarations.forEach((symbol, declarationMirror) { |
| 557 if (declarationMirror is ClassMirror) { | 783 if (declarationMirror is ClassMirror) { |
| 558 var name = MirrorSystem.getName(symbol); | 784 var name = MirrorSystem.getName(symbol); |
| 559 if (declarationMirror.hasReflectedType | 785 if (declarationMirror.hasReflectedType && |
| 560 && !properties.containsKey(name)) { | 786 !properties.containsKey(name)) { |
| 561 properties[name] = new _Property(name) | 787 properties[name] = new _Property(name) |
| 562 ..value = declarationMirror.reflectedType; | 788 ..value = declarationMirror.reflectedType; |
| 563 } | 789 } |
| 564 } | 790 } |
| 565 }); | 791 }); |
| 566 } | 792 } |
| 567 return packageProperties(properties); | 793 return packageProperties(properties); |
| 568 } | 794 } |
| 569 | 795 |
| 570 static List getObjectProperties(o, bool ownProperties, | 796 static List getObjectProperties( |
| 571 bool accessorPropertiesOnly) { | 797 o, bool ownProperties, bool accessorPropertiesOnly) { |
| 572 var properties = new Map<String, _Property>(); | 798 var properties = new Map<String, _Property>(); |
| 573 var names = new Set<String>(); | 799 var names = new Set<String>(); |
| 574 var objectMirror = reflect(o); | 800 var objectMirror = reflect(o); |
| 575 var classMirror = objectMirror.type; | 801 var classMirror = objectMirror.type; |
| 576 _addInstanceMirrors(objectMirror, classMirror.owner, | 802 _addInstanceMirrors( |
| 803 objectMirror, | |
| 804 classMirror.owner, | |
| 577 classMirror.instanceMembers, | 805 classMirror.instanceMembers, |
| 578 ownProperties, accessorPropertiesOnly, false, true, | 806 ownProperties, |
| 807 accessorPropertiesOnly, | |
| 808 false, | |
| 809 true, | |
| 579 properties); | 810 properties); |
| 580 return packageProperties(properties); | 811 return packageProperties(properties); |
| 581 } | 812 } |
| 582 | 813 |
| 583 static List getObjectClassProperties(o, bool ownProperties, | 814 static List getObjectClassProperties( |
| 584 bool accessorPropertiesOnly) { | 815 o, bool ownProperties, bool accessorPropertiesOnly) { |
| 585 var properties = new Map<String, _Property>(); | 816 var properties = new Map<String, _Property>(); |
| 586 var objectMirror = reflect(o); | 817 var objectMirror = reflect(o); |
| 587 var classMirror = objectMirror.type; | 818 var classMirror = objectMirror.type; |
| 588 _addInstanceMirrors(objectMirror, classMirror.owner, | 819 _addInstanceMirrors( |
| 820 objectMirror, | |
| 821 classMirror.owner, | |
| 589 classMirror.instanceMembers, | 822 classMirror.instanceMembers, |
| 590 ownProperties, accessorPropertiesOnly, true, false, | 823 ownProperties, |
| 824 accessorPropertiesOnly, | |
| 825 true, | |
| 826 false, | |
| 591 properties); | 827 properties); |
| 592 _addStatics(classMirror, properties, accessorPropertiesOnly); | 828 _addStatics(classMirror, properties, accessorPropertiesOnly); |
| 593 return packageProperties(properties); | 829 return packageProperties(properties); |
| 594 } | 830 } |
| 595 | 831 |
| 596 static List getClassProperties(Type t, bool ownProperties, | 832 static List getClassProperties( |
| 597 bool accessorPropertiesOnly) { | 833 Type t, bool ownProperties, bool accessorPropertiesOnly) { |
| 598 var properties = new Map<String, _Property>(); | 834 var properties = new Map<String, _Property>(); |
| 599 var classMirror = reflectClass(t); | 835 var classMirror = reflectClass(t); |
| 600 _addStatics(classMirror, properties, accessorPropertiesOnly); | 836 _addStatics(classMirror, properties, accessorPropertiesOnly); |
| 601 return packageProperties(properties); | 837 return packageProperties(properties); |
| 602 } | 838 } |
| 603 | 839 |
| 604 static void _addStatics(ClassMirror classMirror, | 840 static void _addStatics(ClassMirror classMirror, |
| 605 Map<String, _Property> properties, | 841 Map<String, _Property> properties, bool accessorPropertiesOnly) { |
| 606 bool accessorPropertiesOnly) { | |
| 607 var libraryMirror = classMirror.owner; | 842 var libraryMirror = classMirror.owner; |
| 608 classMirror.declarations.forEach((symbol, declaration) { | 843 classMirror.declarations.forEach((symbol, declaration) { |
| 609 var name = _getShortSymbolName(symbol, declaration); | 844 var name = _getShortSymbolName(symbol, declaration); |
| 610 if (name.isEmpty) return; | 845 if (name.isEmpty) return; |
| 611 if (declaration is VariableMirror) { | 846 if (declaration is VariableMirror) { |
| 612 if (accessorPropertiesOnly) return; | 847 if (accessorPropertiesOnly) return; |
| 613 if (!declaration.isStatic) return; | 848 if (!declaration.isStatic) return; |
| 614 properties.putIfAbsent(name, () => new _Property(name)) | 849 properties.putIfAbsent(name, () => new _Property(name)) |
| 615 ..value = classMirror.getField(symbol).reflectee | 850 ..value = classMirror.getField(symbol).reflectee |
| 616 ..writable = !declaration.isFinal && !declaration.isConst; | 851 ..writable = !declaration.isFinal && !declaration.isConst; |
| 617 } else if (declaration is MethodMirror) { | 852 } else if (declaration is MethodMirror) { |
| 618 MethodMirror methodMirror = declaration; | 853 MethodMirror methodMirror = declaration; |
| 619 // FIXMEDART: should we display constructors? | 854 // FIXMEDART: should we display constructors? |
| 620 if (methodMirror.isConstructor) return; | 855 if (methodMirror.isConstructor) return; |
| 621 if (!methodMirror.isStatic) return; | 856 if (!methodMirror.isStatic) return; |
| 622 if (accessorPropertiesOnly) { | 857 if (accessorPropertiesOnly) { |
| 623 if (methodMirror.isRegularMethod || | 858 if (methodMirror.isRegularMethod || |
| 624 treatPropertyAsField(methodMirror, libraryMirror)) { | 859 treatPropertyAsField(methodMirror, libraryMirror)) { |
| 625 return; | 860 return; |
| 626 } | 861 } |
| 627 } else if (!methodMirror.isRegularMethod && | 862 } else if (!methodMirror.isRegularMethod && |
| 628 !treatPropertyAsField(methodMirror, libraryMirror)) { | 863 !treatPropertyAsField(methodMirror, libraryMirror)) { |
| 629 return; | 864 return; |
| 630 } | 865 } |
| 631 var property = properties.putIfAbsent(name, () => new _Property(name)); | 866 var property = properties.putIfAbsent(name, () => new _Property(name)); |
| 632 _fillMethodMirrorProperty(libraryMirror, classMirror, methodMirror, | 867 _fillMethodMirrorProperty(libraryMirror, classMirror, methodMirror, |
| 633 symbol, accessorPropertiesOnly, property); | 868 symbol, accessorPropertiesOnly, property); |
| 634 } | 869 } |
| 635 }); | 870 }); |
| 636 } | 871 } |
| 637 | 872 |
| 638 static void _fillMethodMirrorProperty(LibraryMirror libraryMirror, | 873 static void _fillMethodMirrorProperty( |
| 639 methodOwner, MethodMirror methodMirror, Symbol symbol, | 874 LibraryMirror libraryMirror, |
| 640 bool accessorPropertiesOnly, _Property property) { | 875 methodOwner, |
| 876 MethodMirror methodMirror, | |
| 877 Symbol symbol, | |
| 878 bool accessorPropertiesOnly, | |
| 879 _Property property) { | |
| 641 if (methodMirror.isRegularMethod) { | 880 if (methodMirror.isRegularMethod) { |
| 642 property | 881 property |
| 643 ..value = new _MethodTrampoline(methodOwner, methodMirror, symbol) | 882 ..value = new _MethodTrampoline(methodOwner, methodMirror, symbol) |
| 644 ..isMethod = true; | 883 ..isMethod = true; |
| 645 } else if (methodMirror.isGetter) { | 884 } else if (methodMirror.isGetter) { |
| 646 if (treatPropertyAsField(methodMirror, libraryMirror)) { | 885 if (treatPropertyAsField(methodMirror, libraryMirror)) { |
| 647 try { | 886 try { |
| 648 property.value = methodOwner.getField(symbol).reflectee; | 887 property.value = methodOwner.getField(symbol).reflectee; |
| 649 } catch (e) { | 888 } catch (e) { |
| 650 property | 889 property |
| 651 ..wasThrown = true | 890 ..wasThrown = true |
| 652 ..value = e; | 891 ..value = e; |
| 653 } | 892 } |
| 654 } else if (accessorPropertiesOnly) { | 893 } else if (accessorPropertiesOnly) { |
| 655 property.getter = new _GetterTrampoline(methodOwner, | 894 property.getter = |
| 656 methodMirror, symbol); | 895 new _GetterTrampoline(methodOwner, methodMirror, symbol); |
| 657 } | 896 } |
| 658 } else if (methodMirror.isSetter) { | 897 } else if (methodMirror.isSetter) { |
| 659 if (accessorPropertiesOnly && | 898 if (accessorPropertiesOnly && |
| 660 !treatPropertyAsField(methodMirror, libraryMirror)) { | 899 !treatPropertyAsField(methodMirror, libraryMirror)) { |
| 661 property.setter = new _SetterTrampoline(methodOwner, | 900 property.setter = new _SetterTrampoline(methodOwner, methodMirror, |
| 662 methodMirror, MirrorSystem.getSymbol(property.name, libraryMirror)); | 901 MirrorSystem.getSymbol(property.name, libraryMirror)); |
| 663 } | 902 } |
| 664 property.writable = true; | 903 property.writable = true; |
| 665 } | 904 } |
| 666 } | 905 } |
| 667 | 906 |
| 668 /** | 907 /** |
| 669 * Helper method that handles collecting up properties from classes | 908 * Helper method that handles collecting up properties from classes |
| 670 * or libraries using the filters [ownProperties], [accessorPropertiesOnly], | 909 * or libraries using the filters [ownProperties], [accessorPropertiesOnly], |
| 671 * [hideFields], and [hideMethods] to determine which properties are | 910 * [hideFields], and [hideMethods] to determine which properties are |
| 672 * collected. [accessorPropertiesOnly] specifies whether all properties | 911 * collected. [accessorPropertiesOnly] specifies whether all properties |
| 673 * should be returned or just accessors. [hideFields] specifies whether | 912 * should be returned or just accessors. [hideFields] specifies whether |
| 674 * fields should be hidden. hideMethods specifies whether methods should be | 913 * fields should be hidden. hideMethods specifies whether methods should be |
| 675 * shown or hidden. [ownProperties] is not currently used but is part of the | 914 * shown or hidden. [ownProperties] is not currently used but is part of the |
| 676 * Blink devtools API for enumerating properties. | 915 * Blink devtools API for enumerating properties. |
| 677 */ | 916 */ |
| 678 static void _addInstanceMirrors( | 917 static void _addInstanceMirrors( |
| 679 ObjectMirror objectMirror, | 918 ObjectMirror objectMirror, |
| 680 LibraryMirror libraryMirror, | 919 LibraryMirror libraryMirror, |
| 681 Map<Symbol, Mirror> declarations, | 920 Map<Symbol, Mirror> declarations, |
| 682 bool ownProperties, bool accessorPropertiesOnly, | 921 bool ownProperties, |
| 683 bool hideFields, bool hideMethods, | 922 bool accessorPropertiesOnly, |
| 923 bool hideFields, | |
| 924 bool hideMethods, | |
| 684 Map<String, _Property> properties) { | 925 Map<String, _Property> properties) { |
| 685 declarations.forEach((symbol, declaration) { | 926 declarations.forEach((symbol, declaration) { |
| 686 if (declaration is TypedefMirror || declaration is ClassMirror) return; | 927 if (declaration is TypedefMirror || declaration is ClassMirror) return; |
| 687 var name = _getShortSymbolName(symbol, declaration); | 928 var name = _getShortSymbolName(symbol, declaration); |
| 688 if (name.isEmpty) return; | 929 if (name.isEmpty) return; |
| 689 bool isField = declaration is VariableMirror || | 930 bool isField = declaration is VariableMirror || |
| 690 (declaration is MethodMirror && | 931 (declaration is MethodMirror && |
| 691 treatPropertyAsField(declaration, libraryMirror)); | 932 treatPropertyAsField(declaration, libraryMirror)); |
| 692 if ((isField && hideFields) || (hideMethods && !isField)) return; | 933 if ((isField && hideFields) || (hideMethods && !isField)) return; |
| 693 if (accessorPropertiesOnly) { | 934 if (accessorPropertiesOnly) { |
| 694 if (declaration is VariableMirror || declaration.isRegularMethod || | 935 if (declaration is VariableMirror || |
| 936 declaration.isRegularMethod || | |
| 695 isField) { | 937 isField) { |
| 696 return; | 938 return; |
| 697 } | 939 } |
| 698 } else if (declaration is MethodMirror && | 940 } else if (declaration is MethodMirror && |
| 699 (declaration.isGetter || declaration.isSetter) && | 941 (declaration.isGetter || declaration.isSetter) && |
| 700 !treatPropertyAsField(declaration, libraryMirror)) { | 942 !treatPropertyAsField(declaration, libraryMirror)) { |
| 701 return; | 943 return; |
| 702 } | 944 } |
| 703 var property = properties.putIfAbsent(name, () => new _Property(name)); | 945 var property = properties.putIfAbsent(name, () => new _Property(name)); |
| 704 if (declaration is VariableMirror) { | 946 if (declaration is VariableMirror) { |
| 705 property | 947 property |
| 706 ..value = objectMirror.getField(symbol).reflectee | 948 ..value = objectMirror.getField(symbol).reflectee |
| 707 ..writable = !declaration.isFinal && !declaration.isConst; | 949 ..writable = !declaration.isFinal && !declaration.isConst; |
| 708 return; | 950 return; |
| 709 } | 951 } |
| 710 _fillMethodMirrorProperty(libraryMirror, objectMirror, declaration, | 952 _fillMethodMirrorProperty(libraryMirror, objectMirror, declaration, |
| 711 symbol, accessorPropertiesOnly, property); | 953 symbol, accessorPropertiesOnly, property); |
| 712 }); | 954 }); |
| 713 } | 955 } |
| 714 | 956 |
| 715 /** | 957 /** |
| 716 * Flatten down the properties data structure into a List that is easy to | 958 * Flatten down the properties data structure into a List that is easy to |
| 717 * access from native code. | 959 * access from native code. |
| 718 */ | 960 */ |
| 719 static List packageProperties(Map<String, _Property> properties) { | 961 static List packageProperties(Map<String, _Property> properties) { |
| 720 var ret = []; | 962 var ret = []; |
| 721 for (var property in properties.values) { | 963 for (var property in properties.values) { |
| 722 ret.addAll([property.name, | 964 ret.addAll([ |
| 723 property.setter, | 965 property.name, |
| 724 property.getter, | 966 property.setter, |
| 725 property.value, | 967 property.getter, |
| 726 property.hasValue, | 968 property.value, |
| 727 property.writable, | 969 property.hasValue, |
| 728 property.isMethod, | 970 property.writable, |
| 729 property.isOwn, | 971 property.isMethod, |
| 730 property.wasThrown]); | 972 property.isOwn, |
| 973 property.wasThrown | |
| 974 ]); | |
| 731 } | 975 } |
| 732 return ret; | 976 return ret; |
| 733 } | 977 } |
| 734 | 978 |
| 735 /** | 979 /** |
| 736 * Get a property, returning null if the property does not exist. | 980 * Get a property, returning null if the property does not exist. |
| 737 * For private property names, we attempt to resolve the property in the | 981 * For private property names, we attempt to resolve the property in the |
| 738 * context of each library that the property name could be associated with. | 982 * context of each library that the property name could be associated with. |
| 739 */ | 983 */ |
| 740 static getObjectPropertySafe(o, String propertyName) { | 984 static getObjectPropertySafe(o, String propertyName) { |
| 741 var objectMirror = reflect(o); | 985 var objectMirror = reflect(o); |
| 742 var classMirror = objectMirror.type; | 986 var classMirror = objectMirror.type; |
| 743 if (propertyName.startsWith("_")) { | 987 if (propertyName.startsWith("_")) { |
| 744 var attemptedLibraries = new Set<LibraryMirror>(); | 988 var attemptedLibraries = new Set<LibraryMirror>(); |
| 745 while (classMirror != null) { | 989 while (classMirror != null) { |
| 746 LibraryMirror library = classMirror.owner; | 990 LibraryMirror library = classMirror.owner; |
| 747 if (!attemptedLibraries.contains(library)) { | 991 if (!attemptedLibraries.contains(library)) { |
| 748 try { | 992 try { |
| 749 return objectMirror.getField( | 993 return objectMirror |
| 750 MirrorSystem.getSymbol(propertyName, library)).reflectee; | 994 .getField(MirrorSystem.getSymbol(propertyName, library)) |
| 751 } catch (e) { } | 995 .reflectee; |
| 996 } catch (e) {} | |
| 752 attemptedLibraries.add(library); | 997 attemptedLibraries.add(library); |
| 753 } | 998 } |
| 754 classMirror = classMirror.superclass; | 999 classMirror = classMirror.superclass; |
| 755 } | 1000 } |
| 756 return null; | 1001 return null; |
| 757 } | 1002 } |
| 758 try { | 1003 try { |
| 759 return objectMirror.getField( | 1004 return objectMirror |
| 760 MirrorSystem.getSymbol(propertyName)).reflectee; | 1005 .getField(MirrorSystem.getSymbol(propertyName)) |
| 1006 .reflectee; | |
| 761 } catch (e) { | 1007 } catch (e) { |
| 762 return null; | 1008 return null; |
| 763 } | 1009 } |
| 764 } | 1010 } |
| 765 | 1011 |
| 766 /** | 1012 /** |
| 767 * Helper to wrap the inspect method on InjectedScriptHost to provide the | 1013 * Helper to wrap the inspect method on InjectedScriptHost to provide the |
| 768 * inspect method required for the | 1014 * inspect method required for the |
| 769 */ | 1015 */ |
| 770 static List consoleApi(host) { | 1016 static List consoleApi(host) { |
| 771 return [ | 1017 return [ |
| 772 "inspect", | 1018 "inspect", |
| 773 (o) { | 1019 (o) { |
| 774 js.JsNative.callMethod(host, "_inspect", [o]); | 1020 js.JsNative.callMethod(host, "_inspect", [o]); |
| 775 return o; | 1021 return o; |
| 776 }, | 1022 }, |
| 777 "dir", | 1023 "dir", |
| 778 window.console.dir, | 1024 window.console.dir, |
| 779 "dirxml", | 1025 "dirxml", |
| 780 window.console.dirxml | 1026 window.console.dirxml |
| 781 // FIXME: add copy method. | 1027 // FIXME: add copy method. |
| 782 ]; | 1028 ]; |
| 783 } | 1029 } |
| 784 | 1030 |
| 785 static List getMapKeyList(Map map) => map.keys.toList(); | 1031 static List getMapKeyList(Map map) => map.keys.toList(); |
| 786 | 1032 |
| 787 static bool isNoSuchMethodError(obj) => obj is NoSuchMethodError; | 1033 static bool isNoSuchMethodError(obj) => obj is NoSuchMethodError; |
| 788 | 1034 |
| 789 static void register(Document document, String tag, Type type, | 1035 static void register( |
| 790 String extendsTagName) { | 1036 Document document, String tag, Type type, String extendsTagName) { |
| 791 var nativeClass = _validateCustomType(type); | 1037 var nativeClass = _validateCustomType(type); |
| 792 | 1038 |
| 793 if (extendsTagName == null) { | 1039 if (extendsTagName == null) { |
| 794 if (nativeClass.reflectedType != HtmlElement) { | 1040 if (nativeClass.reflectedType != HtmlElement) { |
| 795 throw new UnsupportedError('Class must provide extendsTag if base ' | 1041 throw new UnsupportedError('Class must provide extendsTag if base ' |
| 796 'native class is not HTMLElement'); | 1042 'native class is not HTMLElement'); |
| 797 } | 1043 } |
| 798 } | 1044 } |
| 799 | 1045 |
| 800 _register(document, tag, type, extendsTagName); | 1046 _register(document, tag, type, extendsTagName); |
| 801 } | 1047 } |
| 802 | 1048 |
| 803 static void _register(Document document, String tag, Type customType, | 1049 static void _register(Document document, String tag, Type customType, |
| 804 String extendsTagName) => _blink.Blink_Utils.register(document, tag, customT ype, extendsTagName); | 1050 String extendsTagName) => |
| 1051 _blink.Blink_Utils.register(document, tag, customType, extendsTagName); | |
| 805 | 1052 |
| 806 static Element createElement(Document document, String tagName) => | 1053 static Element createElement(Document document, String tagName) => |
| 807 _blink.Blink_Utils.createElement(document, tagName); | 1054 _blink.Blink_Utils.createElement(document, tagName); |
| 808 } | 1055 } |
| 809 | 1056 |
| 810 // TODO(jacobr): this seems busted. I believe we are actually | 1057 // TODO(jacobr): this seems busted. I believe we are actually |
| 811 // giving users real windows for opener, parent, top, etc. | 1058 // giving users real windows for opener, parent, top, etc. |
| 812 // Or worse, we are probaly returning a raw JSObject. | 1059 // Or worse, we are probaly returning a raw JSObject. |
| 813 class _DOMWindowCrossFrame extends DartHtmlDomObject implements | 1060 class _DOMWindowCrossFrame extends DartHtmlDomObject implements WindowBase { |
| 814 WindowBase { | 1061 _DOMWindowCrossFrame.internal(); |
| 815 | 1062 |
| 816 _DOMWindowCrossFrame.internal(); | 1063 static _createSafe(win) => |
| 817 | 1064 _blink.Blink_Utils.setInstanceInterceptor(win, _DOMWindowCrossFrame); |
| 818 static _createSafe(win) => _blink.Blink_Utils.setInstanceInterceptor(win, _DOM WindowCrossFrame); | |
| 819 | 1065 |
| 820 // Fields. | 1066 // Fields. |
| 821 HistoryBase get history => _blink.Blink_DOMWindowCrossFrame.get_history(this); | 1067 HistoryBase get history => _blink.Blink_DOMWindowCrossFrame.get_history(this); |
| 822 LocationBase get location => _blink.Blink_DOMWindowCrossFrame.get_location(thi s); | 1068 LocationBase get location => |
| 1069 _blink.Blink_DOMWindowCrossFrame.get_location(this); | |
| 823 bool get closed => _blink.Blink_DOMWindowCrossFrame.get_closed(this); | 1070 bool get closed => _blink.Blink_DOMWindowCrossFrame.get_closed(this); |
| 824 WindowBase get opener => _blink.Blink_DOMWindowCrossFrame.get_opener(this); | 1071 WindowBase get opener => _blink.Blink_DOMWindowCrossFrame.get_opener(this); |
| 825 WindowBase get parent => _blink.Blink_DOMWindowCrossFrame.get_parent(this); | 1072 WindowBase get parent => _blink.Blink_DOMWindowCrossFrame.get_parent(this); |
| 826 WindowBase get top => _blink.Blink_DOMWindowCrossFrame.get_top(this); | 1073 WindowBase get top => _blink.Blink_DOMWindowCrossFrame.get_top(this); |
| 827 | 1074 |
| 828 // Methods. | 1075 // Methods. |
| 829 void close() => _blink.Blink_DOMWindowCrossFrame.close(this); | 1076 void close() => _blink.Blink_DOMWindowCrossFrame.close(this); |
| 830 void postMessage(/*SerializedScriptValue*/ message, String targetOrigin, [List messagePorts]) => | 1077 void postMessage(/*SerializedScriptValue*/ message, String targetOrigin, |
| 831 _blink.Blink_DOMWindowCrossFrame.postMessage(this, | 1078 [List messagePorts]) => |
| 832 convertDartToNative_SerializedScriptValue(message), targetOrigin, messa gePorts); | 1079 _blink.Blink_DOMWindowCrossFrame.postMessage( |
| 1080 this, | |
| 1081 convertDartToNative_SerializedScriptValue(message), | |
| 1082 targetOrigin, | |
| 1083 messagePorts); | |
| 833 | 1084 |
| 834 // Implementation support. | 1085 // Implementation support. |
| 835 String get typeName => "Window"; | 1086 String get typeName => "Window"; |
| 836 | 1087 |
| 837 // TODO(efortuna): Remove this method. dartbug.com/16814 | 1088 // TODO(efortuna): Remove this method. dartbug.com/16814 |
| 838 Events get on => throw new UnsupportedError( | 1089 Events get on => throw new UnsupportedError( |
| 839 'You can only attach EventListeners to your own window.'); | 1090 'You can only attach EventListeners to your own window.'); |
| 840 // TODO(efortuna): Remove this method. dartbug.com/16814 | 1091 // TODO(efortuna): Remove this method. dartbug.com/16814 |
| 841 void _addEventListener([String type, EventListener listener, bool useCapture]) | 1092 void _addEventListener( |
| 842 => throw new UnsupportedError( | 1093 [String type, EventListener listener, bool useCapture]) => |
| 843 'You can only attach EventListeners to your own window.'); | 1094 throw new UnsupportedError( |
| 1095 'You can only attach EventListeners to your own window.'); | |
| 844 // TODO(efortuna): Remove this method. dartbug.com/16814 | 1096 // TODO(efortuna): Remove this method. dartbug.com/16814 |
| 845 void addEventListener(String type, EventListener listener, [bool useCapture]) | 1097 void addEventListener(String type, EventListener listener, |
| 846 => throw new UnsupportedError( | 1098 [bool useCapture]) => |
| 847 'You can only attach EventListeners to your own window.'); | 1099 throw new UnsupportedError( |
| 1100 'You can only attach EventListeners to your own window.'); | |
| 848 // TODO(efortuna): Remove this method. dartbug.com/16814 | 1101 // TODO(efortuna): Remove this method. dartbug.com/16814 |
| 849 bool dispatchEvent(Event event) => throw new UnsupportedError( | 1102 bool dispatchEvent(Event event) => throw new UnsupportedError( |
| 850 'You can only attach EventListeners to your own window.'); | 1103 'You can only attach EventListeners to your own window.'); |
| 851 // TODO(efortuna): Remove this method. dartbug.com/16814 | 1104 // TODO(efortuna): Remove this method. dartbug.com/16814 |
| 852 void _removeEventListener([String type, EventListener listener, | 1105 void _removeEventListener( |
| 853 bool useCapture]) => throw new UnsupportedError( | 1106 [String type, EventListener listener, bool useCapture]) => |
| 854 'You can only attach EventListeners to your own window.'); | 1107 throw new UnsupportedError( |
| 1108 'You can only attach EventListeners to your own window.'); | |
| 855 // TODO(efortuna): Remove this method. dartbug.com/16814 | 1109 // TODO(efortuna): Remove this method. dartbug.com/16814 |
| 856 void removeEventListener(String type, EventListener listener, | 1110 void removeEventListener(String type, EventListener listener, |
| 857 [bool useCapture]) => throw new UnsupportedError( | 1111 [bool useCapture]) => |
| 858 'You can only attach EventListeners to your own window.'); | 1112 throw new UnsupportedError( |
| 1113 'You can only attach EventListeners to your own window.'); | |
| 859 } | 1114 } |
| 860 | 1115 |
| 861 class _HistoryCrossFrame extends DartHtmlDomObject implements HistoryBase { | 1116 class _HistoryCrossFrame extends DartHtmlDomObject implements HistoryBase { |
| 862 _HistoryCrossFrame.internal(); | 1117 _HistoryCrossFrame.internal(); |
| 863 | 1118 |
| 864 // Methods. | 1119 // Methods. |
| 865 void back() => _blink.Blink_HistoryCrossFrame.back(this); | 1120 void back() => _blink.Blink_HistoryCrossFrame.back(this); |
| 866 void forward() => _blink.Blink_HistoryCrossFrame.forward(this); | 1121 void forward() => _blink.Blink_HistoryCrossFrame.forward(this); |
| 867 void go(int distance) => _blink.Blink_HistoryCrossFrame.go(this, distance); | 1122 void go(int distance) => _blink.Blink_HistoryCrossFrame.go(this, distance); |
| 868 | 1123 |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 890 final port = new ReceivePort(); | 1145 final port = new ReceivePort(); |
| 891 port.listen((result) { | 1146 port.listen((result) { |
| 892 completer.complete(result); | 1147 completer.complete(result); |
| 893 port.close(); | 1148 port.close(); |
| 894 }); | 1149 }); |
| 895 // TODO: SendPort.hashCode is ugly way to access port id. | 1150 // TODO: SendPort.hashCode is ugly way to access port id. |
| 896 spawnRequest(port.sendPort.hashCode); | 1151 spawnRequest(port.sendPort.hashCode); |
| 897 return completer.future; | 1152 return completer.future; |
| 898 } | 1153 } |
| 899 | 1154 |
| 900 Future<SendPort> _spawnDomHelper(Function f) => | 1155 Future<SendPort> _spawnDomHelper(Function f) => _makeSendPortFuture((portId) { |
| 901 _makeSendPortFuture((portId) { _Utils.spawnDomHelper(f, portId); }); | 1156 _Utils.spawnDomHelper(f, portId); |
| 1157 }); | |
| 902 | 1158 |
| 903 final Future<SendPort> __HELPER_ISOLATE_PORT = | 1159 final Future<SendPort> __HELPER_ISOLATE_PORT = |
| 904 _spawnDomHelper(_helperIsolateMain); | 1160 _spawnDomHelper(_helperIsolateMain); |
| 905 | 1161 |
| 906 // Tricky part. | 1162 // Tricky part. |
| 907 // Once __HELPER_ISOLATE_PORT gets resolved, it will still delay in .then | 1163 // Once __HELPER_ISOLATE_PORT gets resolved, it will still delay in .then |
| 908 // and to delay Timer.run is used. However, Timer.run will try to register | 1164 // and to delay Timer.run is used. However, Timer.run will try to register |
| 909 // another Timer and here we got stuck: event cannot be posted as then | 1165 // another Timer and here we got stuck: event cannot be posted as then |
| 910 // callback is not executed because it's delayed with timer. | 1166 // callback is not executed because it's delayed with timer. |
| 911 // Therefore once future is resolved, it's unsafe to call .then on it | 1167 // Therefore once future is resolved, it's unsafe to call .then on it |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 933 _helperIsolateMain(originalSendPort) { | 1189 _helperIsolateMain(originalSendPort) { |
| 934 var port = new ReceivePort(); | 1190 var port = new ReceivePort(); |
| 935 originalSendPort.send(port.sendPort); | 1191 originalSendPort.send(port.sendPort); |
| 936 port.listen((args) { | 1192 port.listen((args) { |
| 937 var msg = args.first; | 1193 var msg = args.first; |
| 938 var replyTo = args.last; | 1194 var replyTo = args.last; |
| 939 final cmd = msg[0]; | 1195 final cmd = msg[0]; |
| 940 if (cmd == _NEW_TIMER) { | 1196 if (cmd == _NEW_TIMER) { |
| 941 final duration = new Duration(milliseconds: msg[1]); | 1197 final duration = new Duration(milliseconds: msg[1]); |
| 942 bool periodic = msg[2]; | 1198 bool periodic = msg[2]; |
| 943 ping() { replyTo.send(_TIMER_PING); }; | 1199 ping() { |
| 944 _TIMER_REGISTRY[replyTo] = periodic ? | 1200 replyTo.send(_TIMER_PING); |
| 945 new Timer.periodic(duration, (_) { ping(); }) : | 1201 } |
| 946 new Timer(duration, ping); | 1202 ; |
| 1203 _TIMER_REGISTRY[replyTo] = periodic | |
| 1204 ? new Timer.periodic(duration, (_) { | |
| 1205 ping(); | |
| 1206 }) | |
| 1207 : new Timer(duration, ping); | |
| 947 } else if (cmd == _CANCEL_TIMER) { | 1208 } else if (cmd == _CANCEL_TIMER) { |
| 948 _TIMER_REGISTRY.remove(replyTo).cancel(); | 1209 _TIMER_REGISTRY.remove(replyTo).cancel(); |
| 949 } else if (cmd == _PRINT) { | 1210 } else if (cmd == _PRINT) { |
| 950 final message = msg[1]; | 1211 final message = msg[1]; |
| 951 // TODO(antonm): we need somehow identify those isolates. | 1212 // TODO(antonm): we need somehow identify those isolates. |
| 952 print('[From isolate] $message'); | 1213 print('[From isolate] $message'); |
| 953 } | 1214 } |
| 954 }); | 1215 }); |
| 955 } | 1216 } |
| 956 | 1217 |
| 957 final _printClosure = (s) => window.console.log(s); | 1218 final _printClosure = (s) => window.console.log(s); |
| 958 final _pureIsolatePrintClosure = (s) { | 1219 final _pureIsolatePrintClosure = (s) { |
| 959 _sendToHelperIsolate([_PRINT, s], null); | 1220 _sendToHelperIsolate([_PRINT, s], null); |
| 960 }; | 1221 }; |
| 961 | 1222 |
| 962 final _forwardingPrintClosure = _Utils.forwardingPrint; | 1223 final _forwardingPrintClosure = _Utils.forwardingPrint; |
| 963 | 1224 |
| 964 final _uriBaseClosure = () => Uri.parse(window.location.href); | 1225 final _uriBaseClosure = () => Uri.parse(window.location.href); |
| 965 | 1226 |
| 966 final _pureIsolateUriBaseClosure = () { | 1227 final _pureIsolateUriBaseClosure = () { |
| 967 throw new UnimplementedError("Uri.base on a background isolate " | 1228 throw new UnimplementedError("Uri.base on a background isolate " |
| 968 "is not supported in the browser"); | 1229 "is not supported in the browser"); |
| 969 }; | 1230 }; |
| 970 | 1231 |
| 971 class _Timer implements Timer { | 1232 class _Timer implements Timer { |
| 972 static const int _STATE_TIMEOUT = 0; | 1233 static const int _STATE_TIMEOUT = 0; |
| 973 static const int _STATE_INTERVAL = 1; | 1234 static const int _STATE_INTERVAL = 1; |
| 974 int _state; | 1235 int _state; |
| 975 | 1236 |
| 976 _Timer(int milliSeconds, void callback(Timer timer), bool repeating) { | 1237 _Timer(int milliSeconds, void callback(Timer timer), bool repeating) { |
| 977 if (repeating) { | 1238 if (repeating) { |
| 978 _state = (window._setInterval(() { | 1239 _state = (window._setInterval(() { |
| 979 callback(this); | 1240 callback(this); |
| 980 }, milliSeconds) << 1) | _STATE_INTERVAL; | 1241 }, milliSeconds) << |
| 1242 1) | | |
| 1243 _STATE_INTERVAL; | |
| 981 } else { | 1244 } else { |
| 982 _state = (window._setTimeout(() { | 1245 _state = (window._setTimeout(() { |
| 983 _state = null; | 1246 _state = null; |
| 984 callback(this); | 1247 callback(this); |
| 985 }, milliSeconds) << 1) | _STATE_TIMEOUT; | 1248 }, milliSeconds) << |
| 1249 1) | | |
| 1250 _STATE_TIMEOUT; | |
| 986 } | 1251 } |
| 987 } | 1252 } |
| 988 | 1253 |
| 989 void cancel() { | 1254 void cancel() { |
| 990 if (_state == null) return; | 1255 if (_state == null) return; |
| 991 int id = _state >> 1; | 1256 int id = _state >> 1; |
| 992 if ((_state & 1) == _STATE_TIMEOUT) { | 1257 if ((_state & 1) == _STATE_TIMEOUT) { |
| 993 window._clearTimeout(id); | 1258 window._clearTimeout(id); |
| 994 } else { | 1259 } else { |
| 995 window._clearInterval(id); | 1260 window._clearInterval(id); |
| 996 } | 1261 } |
| 997 _state = null; | 1262 _state = null; |
| 998 } | 1263 } |
| 999 | 1264 |
| 1000 bool get isActive => _state != null; | 1265 bool get isActive => _state != null; |
| 1001 } | 1266 } |
| 1002 | 1267 |
| 1003 get _timerFactoryClosure => | 1268 get _timerFactoryClosure => |
| 1004 (int milliSeconds, void callback(Timer timer), bool repeating) { | 1269 (int milliSeconds, void callback(Timer timer), bool repeating) { |
| 1005 return new _Timer(milliSeconds, callback, repeating); | 1270 return new _Timer(milliSeconds, callback, repeating); |
| 1006 }; | 1271 }; |
| 1007 | 1272 |
| 1008 class _PureIsolateTimer implements Timer { | 1273 class _PureIsolateTimer implements Timer { |
| 1009 bool _isActive = true; | 1274 bool _isActive = true; |
| 1010 final ReceivePort _port = new ReceivePort(); | 1275 final ReceivePort _port = new ReceivePort(); |
| 1011 SendPort _sendPort; // Effectively final. | 1276 SendPort _sendPort; // Effectively final. |
| 1012 | 1277 |
| 1013 // static SendPort _SEND_PORT; | 1278 // static SendPort _SEND_PORT; |
| 1014 | 1279 |
| 1015 _PureIsolateTimer(int milliSeconds, callback, repeating) { | 1280 _PureIsolateTimer(int milliSeconds, callback, repeating) { |
| 1016 _sendPort = _port.sendPort; | 1281 _sendPort = _port.sendPort; |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 1036 | 1301 |
| 1037 _send(msg) { | 1302 _send(msg) { |
| 1038 _sendToHelperIsolate(msg, _sendPort); | 1303 _sendToHelperIsolate(msg, _sendPort); |
| 1039 } | 1304 } |
| 1040 | 1305 |
| 1041 bool get isActive => _isActive; | 1306 bool get isActive => _isActive; |
| 1042 } | 1307 } |
| 1043 | 1308 |
| 1044 get _pureIsolateTimerFactoryClosure => | 1309 get _pureIsolateTimerFactoryClosure => |
| 1045 ((int milliSeconds, void callback(Timer time), bool repeating) => | 1310 ((int milliSeconds, void callback(Timer time), bool repeating) => |
| 1046 new _PureIsolateTimer(milliSeconds, callback, repeating)); | 1311 new _PureIsolateTimer(milliSeconds, callback, repeating)); |
| 1047 | 1312 |
| 1048 class _ScheduleImmediateHelper { | 1313 class _ScheduleImmediateHelper { |
| 1049 MutationObserver _observer; | 1314 MutationObserver _observer; |
| 1050 final DivElement _div = new DivElement(); | 1315 final DivElement _div = new DivElement(); |
| 1051 Function _callback; | 1316 Function _callback; |
| 1052 | 1317 |
| 1053 _ScheduleImmediateHelper() { | 1318 _ScheduleImmediateHelper() { |
| 1054 // Run in the root-zone as the DOM callback would otherwise execute in the | 1319 // Run in the root-zone as the DOM callback would otherwise execute in the |
| 1055 // current zone. | 1320 // current zone. |
| 1056 Zone.ROOT.run(() { | 1321 Zone.ROOT.run(() { |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 1075 var tmp = _callback; | 1340 var tmp = _callback; |
| 1076 _callback = null; | 1341 _callback = null; |
| 1077 tmp(); | 1342 tmp(); |
| 1078 } | 1343 } |
| 1079 } | 1344 } |
| 1080 | 1345 |
| 1081 final _ScheduleImmediateHelper _scheduleImmediateHelper = | 1346 final _ScheduleImmediateHelper _scheduleImmediateHelper = |
| 1082 new _ScheduleImmediateHelper(); | 1347 new _ScheduleImmediateHelper(); |
| 1083 | 1348 |
| 1084 get _scheduleImmediateClosure => (void callback()) { | 1349 get _scheduleImmediateClosure => (void callback()) { |
| 1085 _scheduleImmediateHelper._schedule(callback); | 1350 _scheduleImmediateHelper._schedule(callback); |
| 1086 }; | 1351 }; |
| 1087 | 1352 |
| 1088 get _pureIsolateScheduleImmediateClosure => ((void callback()) => | 1353 get _pureIsolateScheduleImmediateClosure => ((void callback()) => |
| 1089 throw new UnimplementedError("scheduleMicrotask in background isolates " | 1354 throw new UnimplementedError("scheduleMicrotask in background isolates " |
| 1090 "are not supported in the browser")); | 1355 "are not supported in the browser")); |
| 1091 | 1356 |
| 1092 // Class for unsupported native browser 'DOM' objects. | 1357 // Class for unsupported native browser 'DOM' objects. |
| 1093 class _UnsupportedBrowserObject extends DartHtmlDomObject { | 1358 class _UnsupportedBrowserObject extends DartHtmlDomObject {} |
| 1094 } | |
| OLD | NEW |