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