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

Side by Side Diff: sdk/lib/js/dartium/js_dartium.dart

Issue 1421133003: Support isExternal method on MethodMirror in the Dart VM. Not really intended for public consumptio… (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: ran formatter on js_dartium.dart Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« runtime/lib/mirrors.cc ('K') | « runtime/lib/mirrors_impl.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 /** 5 /**
6 * Support for interoperating with JavaScript. 6 * Support for interoperating with JavaScript.
7 * 7 *
8 * This library provides access to JavaScript objects from Dart, allowing 8 * This library provides access to JavaScript objects from Dart, allowing
9 * Dart code to get and set properties, and call methods of JavaScript objects 9 * Dart code to get and set properties, and call methods of JavaScript objects
10 * and invoke JavaScript functions. The library takes care of converting 10 * and invoke JavaScript functions. The library takes care of converting
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 import 'dart:typed_data'; 97 import 'dart:typed_data';
98 98
99 // Pretend we are always in checked mode as we aren't interested in users 99 // Pretend we are always in checked mode as we aren't interested in users
100 // running Dartium code outside of checked mode. 100 // running Dartium code outside of checked mode.
101 final bool CHECK_JS_INVOCATIONS = true; 101 final bool CHECK_JS_INVOCATIONS = true;
102 102
103 final _allowedMethods = new Map<Symbol, _DeclarationSet>(); 103 final _allowedMethods = new Map<Symbol, _DeclarationSet>();
104 final _allowedGetters = new Map<Symbol, _DeclarationSet>(); 104 final _allowedGetters = new Map<Symbol, _DeclarationSet>();
105 final _allowedSetters = new Map<Symbol, _DeclarationSet>(); 105 final _allowedSetters = new Map<Symbol, _DeclarationSet>();
106 106
107 final _jsInterfaceTypes = new Set<Type>(); 107 final _jsInterfaceTypes = new Set<mirrors.ClassMirror>();
108 Iterable<Type> get jsInterfaceTypes => _jsInterfaceTypes; 108 Iterable<mirrors.ClassMirror> get jsInterfaceTypes => _jsInterfaceTypes;
109 109
110 /// A collection of methods where all methods have the same name. 110 /// A collection of methods where all methods have the same name.
111 /// This class is intended to optimize whether a specific invocation is 111 /// This class is intended to optimize whether a specific invocation is
112 /// appropritate for at least some of the methods in the collection. 112 /// appropritate for at least some of the methods in the collection.
113 class _DeclarationSet { 113 class _DeclarationSet {
114 _DeclarationSet() : _members = <mirrors.DeclarationMirror>[]; 114 _DeclarationSet() : _members = <mirrors.DeclarationMirror>[];
115 115
116 static bool _checkType(obj, mirrors.TypeMirror type) { 116 static bool _checkType(obj, mirrors.TypeMirror type) {
117 if (obj == null) return true; 117 if (obj == null) return true;
118 return mirrors.reflectType(obj.runtimeType).isSubtypeOf(type); 118 return mirrors.reflectType(obj.runtimeType).isSubtypeOf(type);
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
206 /** 206 /**
207 * Temporary method that we hope to remove at some point. This method should 207 * Temporary method that we hope to remove at some point. This method should
208 * generally only be called by machine generated code. 208 * generally only be called by machine generated code.
209 */ 209 */
210 void registerJsInterfaces([List<Type> classes]) { 210 void registerJsInterfaces([List<Type> classes]) {
211 // This method is now obsolete in Dartium. 211 // This method is now obsolete in Dartium.
212 } 212 }
213 213
214 void _registerJsInterfaces(List<Type> classes) { 214 void _registerJsInterfaces(List<Type> classes) {
215 for (Type type in classes) { 215 for (Type type in classes) {
216 if (!_jsInterfaceTypes.add(type)) continue; // Already registered.
217 mirrors.ClassMirror typeMirror = mirrors.reflectType(type); 216 mirrors.ClassMirror typeMirror = mirrors.reflectType(type);
218 typeMirror.declarations.forEach((symbol, declaration) { 217 typeMirror.declarations.forEach((symbol, declaration) {
219 if (declaration is mirrors.MethodMirror || 218 if (declaration is mirrors.MethodMirror ||
220 declaration is mirrors.VariableMirror && !declaration.isStatic) { 219 declaration is mirrors.VariableMirror && !declaration.isStatic) {
221 bool treatAsGetter = false; 220 bool treatAsGetter = false;
222 bool treatAsSetter = false; 221 bool treatAsSetter = false;
223 if (declaration is mirrors.VariableMirror) { 222 if (declaration is mirrors.VariableMirror) {
224 treatAsGetter = true; 223 treatAsGetter = true;
225 if (!declaration.isConst && !declaration.isFinal) { 224 if (!declaration.isConst && !declaration.isFinal) {
226 treatAsSetter = true; 225 treatAsSetter = true;
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
259 String _getJsName(mirrors.DeclarationMirror mirror) { 258 String _getJsName(mirrors.DeclarationMirror mirror) {
260 for (var annotation in mirror.metadata) { 259 for (var annotation in mirror.metadata) {
261 if (mirrors.MirrorSystem.getName(annotation.type.simpleName) == "JS") { 260 if (mirrors.MirrorSystem.getName(annotation.type.simpleName) == "JS") {
262 mirrors.LibraryMirror library = annotation.type.owner; 261 mirrors.LibraryMirror library = annotation.type.owner;
263 var uri = library.uri; 262 var uri = library.uri;
264 // make sure the annotation is from package://js 263 // make sure the annotation is from package://js
265 if (uri.scheme == 'package' && uri.path == 'js/js.dart') { 264 if (uri.scheme == 'package' && uri.path == 'js/js.dart') {
266 try { 265 try {
267 var name = annotation.reflectee.name; 266 var name = annotation.reflectee.name;
268 return name != null ? name : ""; 267 return name != null ? name : "";
269 } catch (e) { 268 } catch (e) {}
270 }
271 } 269 }
272 } 270 }
273 } 271 }
274 return null; 272 return null;
275 } 273 }
276 274
277 bool _hasJsName(mirrors.DeclarationMirror mirror) => 275 bool _isAnonymousClass(mirrors.ClassMirror mirror) {
278 _getJsName(mirror) != null; 276 for (var annotation in mirror.metadata) {
277 if (mirrors.MirrorSystem.getName(annotation.type.simpleName) ==
278 "_Anonymous") {
279 mirrors.LibraryMirror library = annotation.type.owner;
280 var uri = library.uri;
281 // make sure the annotation is from package://js
282 if (uri.scheme == 'package' && uri.path == 'js/js.dart') {
283 return true;
284 }
285 }
286 }
287 return false;
288 }
279 289
290 bool _hasJsName(mirrors.DeclarationMirror mirror) => _getJsName(mirror) != null;
280 291
281 _getJsMemberName(mirrors.DeclarationMirror mirror) { 292 _getJsMemberName(mirrors.DeclarationMirror mirror) {
282 var name = _getJsName(mirror); 293 var name = _getJsName(mirror);
283 return name == null || name.isEmpty ? _getDeclarationName(mirror) : 294 return name == null || name.isEmpty ? _getDeclarationName(mirror) : name;
284 name;
285 } 295 }
286 296
287 // TODO(jacobr): handle setters correctyl. 297 // TODO(jacobr): handle setters correctyl.
288 String _getDeclarationName(mirrors.DeclarationMirror declaration) { 298 String _getDeclarationName(mirrors.DeclarationMirror declaration) {
289 var name = mirrors.MirrorSystem.getName(declaration.simpleName); 299 var name = mirrors.MirrorSystem.getName(declaration.simpleName);
290 if (declaration is mirrors.MethodMirror && declaration.isSetter) { 300 if (declaration is mirrors.MethodMirror && declaration.isSetter) {
291 assert(name.endsWith("=")); 301 assert(name.endsWith("="));
292 name = name.substring(0, name.length - 1); 302 name = name.substring(0, name.length - 1);
293 } 303 }
294 return name; 304 return name;
295 } 305 }
296 306
297 final _JS_LIBRARY_PREFIX = "js_library"; 307 final _JS_LIBRARY_PREFIX = "js_library";
298 final _UNDEFINED_VAR = "_UNDEFINED_JS_CONST"; 308 final _UNDEFINED_VAR = "_UNDEFINED_JS_CONST";
299 309
300 String _accessJsPath(String path) => 310 String _accessJsPath(String path) =>
301 "${_JS_LIBRARY_PREFIX}.context${path.split(".").map((p) => "['$p']").join('' )}"; 311 "${_JS_LIBRARY_PREFIX}.context${path.split(".").map((p) => "['$p']").join('' )}";
302 312
303 @Deprecated("Internal Use Only") 313 @Deprecated("Internal Use Only")
304 void addMemberHelper(mirrors.MethodMirror declaration, String path, StringBuffer sb, {bool isStatic: false, String memberName}) { 314 void addMemberHelper(
305 var jsName = _getJsMemberName(declaration); 315 mirrors.MethodMirror declaration, String path, StringBuffer sb,
306 path = (path != null && path.isNotEmpty) ? "${path}.${jsName}" : jsName; 316 {bool isStatic: false, String memberName}) {
317 if (!declaration.isConstructor) {
318 var jsName = _getJsMemberName(declaration);
319 path = (path != null && path.isNotEmpty) ? "${path}.${jsName}" : jsName;
320 }
307 var name = memberName != null ? memberName : _getDeclarationName(declaration); 321 var name = memberName != null ? memberName : _getDeclarationName(declaration);
308 if (declaration.isConstructor) { 322 if (declaration.isConstructor) {
309 sb.write("factory"); 323 sb.write("factory");
310 } else if (isStatic) { 324 } else if (isStatic) {
311 sb.write("static"); 325 sb.write("static");
312 } else { 326 } else {
313 sb.write("patch"); 327 sb.write("patch");
314 } 328 }
315 sb.write(" "); 329 sb.write(" ");
316 if (declaration.isGetter) { 330 if (declaration.isGetter) {
(...skipping 22 matching lines...) Expand all
339 sb.write("=${_UNDEFINED_VAR}"); 353 sb.write("=${_UNDEFINED_VAR}");
340 } 354 }
341 i++; 355 i++;
342 } 356 }
343 if (hasOptional) { 357 if (hasOptional) {
344 sb.write("]"); 358 sb.write("]");
345 } 359 }
346 // TODO(jacobr): 360 // TODO(jacobr):
347 sb.write(") => "); 361 sb.write(") => ");
348 if (declaration.isConstructor) { 362 if (declaration.isConstructor) {
349 sb.write("new ${_JS_LIBRARY_PREFIX}.JsObject("); 363 sb.write("new ${_JS_LIBRARY_PREFIX}.JsObject(");
350 } 364 }
351 sb 365 sb
352 ..write(_accessJsPath(path)) 366 ..write(_accessJsPath(path))
353 ..write(declaration.isConstructor ? "," : ".apply(") 367 ..write(declaration.isConstructor ? "," : ".apply(")
354 ..write("[${args.join(",")}]"); 368 ..write("[${args.join(",")}]");
355 369
356 if (hasOptional) { 370 if (hasOptional) {
357 sb.write(".takeWhile((i) => i != ${_UNDEFINED_VAR}).toList()"); 371 sb.write(".takeWhile((i) => i != ${_UNDEFINED_VAR}).toList()");
358 } 372 }
359 sb.write(");"); 373 sb.write(");");
360 } 374 }
361 sb.write("\n"); 375 sb.write("\n");
362 } 376 }
363 377
364 // TODO(jacobr): make this check more robust. 378 // TODO(jacobr): make this check more robust.
365 bool _isExternal(mirrors.MethodMirror mirror) => 379 bool _isExternal(mirrors.Mirror mirror) {
366 mirror.source != null && mirror.source.startsWith("external "); 380 /*
381 var source = mirror.source;
382 return source != null && source.startsWith("external ");
383 */
384 return mirror.isExternal;
385 }
367 386
368 List<String> _generateExternalMethods() { 387 List<String> _generateExternalMethods() {
369 var staticCodegen = <String>[]; 388 var staticCodegen = <String>[];
370 mirrors.currentMirrorSystem().libraries.forEach((uri, library) { 389 mirrors.currentMirrorSystem().libraries.forEach((uri, library) {
371 var sb = new StringBuffer(); 390 var sb = new StringBuffer();
372 String jsLibraryName = _getJsName(library); 391 String jsLibraryName = _getJsName(library);
373 library.declarations.forEach((name, declaration) { 392 library.declarations.forEach((name, declaration) {
374 if (declaration is mirrors.MethodMirror) { 393 if (declaration is mirrors.MethodMirror) {
375 if (_isExternal(declaration) && (_hasJsName(declaration) || jsLibraryNam e != null)) { 394 if ((_hasJsName(declaration) || jsLibraryName != null) &&
395 _isExternal(declaration)) {
376 addMemberHelper(declaration, jsLibraryName, sb); 396 addMemberHelper(declaration, jsLibraryName, sb);
377 } 397 }
378 } else if (declaration is mirrors.ClassMirror) { 398 } else if (declaration is mirrors.ClassMirror) {
379 mirrors.ClassMirror clazz = declaration; 399 mirrors.ClassMirror clazz = declaration;
380 if (_hasJsName(clazz)) { 400 if (_hasJsName(clazz)) {
381 // TODO(jacobr): verify class implements JavaScriptObject. 401 // TODO(jacobr): verify class implements JavaScriptObject.
382 assert(clazz.hasReflectedType);
383 jsInterfaceTypes.add(clazz.reflectedType);
384 String jsClassName = _getJsMemberName(clazz); 402 String jsClassName = _getJsMemberName(clazz);
385 var className = mirrors.MirrorSystem.getName(clazz.simpleName); 403 var className = mirrors.MirrorSystem.getName(clazz.simpleName);
386 var sbPatch = new StringBuffer(); 404 var sbPatch = new StringBuffer();
405 jsInterfaceTypes.add(clazz);
387 clazz.declarations.forEach((name, declaration) { 406 clazz.declarations.forEach((name, declaration) {
388 if (declaration is! mirrors.MethodMirror || !_isExternal(declaration )) return; 407 if (declaration is! mirrors.MethodMirror ||
389 if (declaration.isFactoryConstructor) { 408 !_isExternal(declaration)) return;
409 if (declaration.isFactoryConstructor && _isAnonymousClass(clazz)) {
390 sbPatch.write(" factory ${className}({"); 410 sbPatch.write(" factory ${className}({");
391 int i = 0; 411 int i = 0;
392 var args = <String>[]; 412 var args = <String>[];
413 for (var p in declaration.parameters) {
414 args.add(mirrors.MirrorSystem.getName(p.simpleName));
415 i++;
416 }
417 sbPatch
418 ..write(
419 args.map((name) => '$name:${_UNDEFINED_VAR}').join(", "))
420 ..write("}) {\n"
421 " var ret = new ${_JS_LIBRARY_PREFIX}.JsObject.jsify({}); \n");
422 i = 0;
423 for (var p in declaration.parameters) {
424 assert(p.isNamed); // XXX throw
425 var name = args[i];
426 var jsName = mirrors.MirrorSystem.getName(p.simpleName);
427 // XXX apply name conversion rules.
428 sbPatch.write(
429 " if($name != ${_UNDEFINED_VAR}) ret['$jsName'] = $name;\ n");
430 i++;
431 }
432
433 sbPatch.write(" return ret;\n"
434 " }\n");
435 } else if (declaration.isConstructor ||
436 declaration.isFactoryConstructor) {
437 sbPatch.write(" ");
438 addMemberHelper(
439 declaration,
440 (jsLibraryName != null && jsLibraryName.isNotEmpty)
441 ? "${jsLibraryName}.${jsClassName}"
442 : jsClassName,
443 sbPatch,
444 isStatic: true,
445 memberName: className);
446 }
447 });
448
449 clazz.staticMembers.forEach((memberName, member) {
450 if (_isExternal(member)) {
451 sbPatch.write(" ");
452 addMemberHelper(
453 member,
454 (jsLibraryName != null && jsLibraryName.isNotEmpty)
455 ? "${jsLibraryName}.${jsClassName}"
456 : jsClassName,
457 sbPatch,
458 isStatic: true);
459 }
460 });
461 var typeVariablesClause = '';
462 if (!clazz.typeVariables.isEmpty) {
463 typeVariablesClause =
464 '<${clazz.typeVariables.map((m) => mirrors.MirrorSystem.getName( m.simpleName)).join(',')}>';
465 }
466 if (sbPatch.isNotEmpty) {
467 sb.write("""
468 patch class $className$typeVariablesClause {
469 $sbPatch
470 }
471 """);
472 }
473 }
474 }
475 });
476 if (sb.isNotEmpty) {
477 staticCodegen
478 ..add(uri.toString())
479 ..add("${uri}_js_interop_patch.dart")
480 ..add("""
481 import 'dart:js' as ${_JS_LIBRARY_PREFIX};
482
483 /**
484 * Placeholder object for cases where we need to determine exactly how many
485 * args were passed to a function.
486 */
487 const ${_UNDEFINED_VAR} = const Object();
488
489 ${sb}
490 """);
491 }
492 });
493
494 return staticCodegen;
495 }
496
497 List<String> _generateExternalMethods2() {
498 var staticCodegen = <String>[];
499 mirrors.currentMirrorSystem().libraries.forEach((uri, library) {
500 var sb = new StringBuffer();
501 String jsLibraryName = _getJsName(library);
502 library.declarations.forEach((name, declaration) {
503 var isExternal = _isExternal(declaration);
504 if (declaration is mirrors.MethodMirror) {
505 if (isExternal && (_hasJsName(declaration) || jsLibraryName != null)) {
506 addMemberHelper(declaration, jsLibraryName, sb);
507 }
508 } else if (declaration is mirrors.ClassMirror) {
509 mirrors.ClassMirror clazz = declaration;
510 if (_hasJsName(clazz)) {
511 // TODO(jacobr): verify class implements JavaScriptObject.
512 String jsClassName = _getJsMemberName(clazz);
513 var className = mirrors.MirrorSystem.getName(clazz.simpleName);
514 var sbPatch = new StringBuffer();
515 jsInterfaceTypes.add(clazz);
516 clazz.declarations.forEach((name, declaration) {
517 if (declaration is! mirrors.MethodMirror ||
518 !declaration.isAbstract ||
519 !isExternal) return;
520 if (_hasLiteralAnnotation(declaration) &&
521 declaration.isFactoryConstructor) {
522 sbPatch.write(" factory ${className}({");
523 int i = 0;
524 var args = <String>[];
393 for (var p in declaration.parameters) { 525 for (var p in declaration.parameters) {
394 assert(p.isNamed); // XXX throw 526 assert(p.isNamed); // XXX throw
395 args.add(mirrors.MirrorSystem.getName(p.simpleName)); 527 args.add(mirrors.MirrorSystem.getName(p.simpleName));
396 i++; 528 i++;
397 } 529 }
398 sbPatch 530 sbPatch
399 ..write(args.map((name) => '$name:${_UNDEFINED_VAR}').join(", ") ) 531 ..write(
532 args.map((name) => '$name:${_UNDEFINED_VAR}').join(", "))
400 ..write("}) {\n" 533 ..write("}) {\n"
401 " var ret = new ${_JS_LIBRARY_PREFIX}.JsObject.jsify( {});\n"); 534 " var ret = new ${_JS_LIBRARY_PREFIX}.JsObject.jsify({}); \n");
402 i = 0; 535 i = 0;
403 for (var p in declaration.parameters) { 536 for (var p in declaration.parameters) {
404 assert(p.isNamed); // XXX throw 537 assert(p.isNamed); // XXX throw
405 var name = args[i]; 538 var name = args[i];
406 var jsName = mirrors.MirrorSystem.getName(p.simpleName); 539 var jsName = mirrors.MirrorSystem.getName(p.simpleName);
407 // XXX apply name conversion rules. 540 // XXX apply name conversion rules.
408 sbPatch.write(" if($name != ${_UNDEFINED_VAR}) ret['$jsName'] = $name;\n"); 541 sbPatch.write(
542 " if($name != ${_UNDEFINED_VAR}) ret['$jsName'] = $name;\ n");
409 i++; 543 i++;
410 } 544 }
411 545
412 sbPatch.write(" return ret;\n" 546 sbPatch.write(" return ret;\n"
413 " }\n"); 547 " }\n");
414 } else if (declaration.isConstructor) { 548 } else if (declaration.isConstructor ||
549 declaration.isFactoryConstructor) {
415 sbPatch.write(" "); 550 sbPatch.write(" ");
416 addMemberHelper(declaration, 551 addMemberHelper(
417 (jsLibraryName != null && jsLibraryName.isNotEmpty) ? "${jsLib raryName}" : "", 552 declaration,
553 (jsLibraryName != null && jsLibraryName.isNotEmpty)
554 ? "${jsLibraryName}.${jsClassName}"
555 : jsClassName,
418 sbPatch, 556 sbPatch,
419 isStatic: true, 557 isStatic: true,
420 memberName: className); 558 memberName: className);
421 } 559 }
422 }); 560 });
423 561
424 clazz.staticMembers.forEach((memberName, member) { 562 clazz.staticMembers.forEach((memberName, member) {
425 if (_isExternal(member)) { 563 if (_isExternal(member)) {
426 sbPatch.write(" "); 564 sbPatch.write(" ");
427 addMemberHelper(member, 565 addMemberHelper(
428 (jsLibraryName != null && jsLibraryName.isNotEmpty) ? "${jsLib raryName}.${jsClassName}" : jsClassName, 566 member,
567 (jsLibraryName != null && jsLibraryName.isNotEmpty)
568 ? "${jsLibraryName}.${jsClassName}"
569 : jsClassName,
429 sbPatch, 570 sbPatch,
430 isStatic: true); 571 isStatic: true);
431 } 572 }
432 }); 573 });
574 var typeVariablesClause = '';
575 if (!clazz.typeVariables.isEmpty) {
576 typeVariablesClause =
577 '<${clazz.typeVariables.map((m) => mirrors.MirrorSystem.getName( m.simpleName)).join(',')}>';
578 }
433 if (sbPatch.isNotEmpty) { 579 if (sbPatch.isNotEmpty) {
434 sb.write(""" 580 sb.write("""
435 patch class $className { 581 patch class $className$typeVariablesClause {
436 $sbPatch 582 $sbPatch
437 } 583 }
438 """); 584 """);
439 } 585 }
440 } 586 }
441 } 587 }
442 }); 588 });
443 if (sb.isNotEmpty) { 589 if (sb.isNotEmpty) {
444 staticCodegen 590 staticCodegen
445 ..add(uri.toString()) 591 ..add(uri.toString())
(...skipping 23 matching lines...) Expand all
469 List<String> _generateInteropPatchFiles() { 615 List<String> _generateInteropPatchFiles() {
470 var ret = _generateExternalMethods(); 616 var ret = _generateExternalMethods();
471 var libraryPrefixes = new Map<mirrors.LibraryMirror, String>(); 617 var libraryPrefixes = new Map<mirrors.LibraryMirror, String>();
472 var prefixNames = new Set<String>(); 618 var prefixNames = new Set<String>();
473 var sb = new StringBuffer(); 619 var sb = new StringBuffer();
474 620
475 var implements = <String>[]; 621 var implements = <String>[];
476 var implementsArray = <String>[]; 622 var implementsArray = <String>[];
477 var listMirror = mirrors.reflectType(List); 623 var listMirror = mirrors.reflectType(List);
478 624
479 for (var type in jsInterfaceTypes) { 625 for (var typeMirror in jsInterfaceTypes) {
480 mirrors.ClassMirror typeMirror = mirrors.reflectType(type);
481 mirrors.LibraryMirror libraryMirror = typeMirror.owner; 626 mirrors.LibraryMirror libraryMirror = typeMirror.owner;
482 var prefixName; 627 var prefixName;
483 if (libraryPrefixes.containsKey(libraryMirror)) { 628 if (libraryPrefixes.containsKey(libraryMirror)) {
484 prefixName = libraryPrefixes[libraryMirror]; 629 prefixName = libraryPrefixes[libraryMirror];
485 } else { 630 } else {
486 var basePrefixName = 631 var basePrefixName =
487 mirrors.MirrorSystem.getName(libraryMirror.simpleName); 632 mirrors.MirrorSystem.getName(libraryMirror.simpleName);
488 basePrefixName = basePrefixName.replaceAll('.', '_'); 633 basePrefixName = basePrefixName.replaceAll('.', '_');
489 if (basePrefixName.isEmpty) basePrefixName = "lib"; 634 if (basePrefixName.isEmpty) basePrefixName = "lib";
490 prefixName = basePrefixName; 635 prefixName = basePrefixName;
491 var i = 1; 636 var i = 1;
492 while (prefixNames.contains(prefixName)) { 637 while (prefixNames.contains(prefixName)) {
493 prefixName = '$basePrefixName$i'; 638 prefixName = '$basePrefixName$i';
494 i++; 639 i++;
495 } 640 }
496 prefixNames.add(prefixName); 641 prefixNames.add(prefixName);
497 libraryPrefixes[libraryMirror] = prefixName; 642 libraryPrefixes[libraryMirror] = prefixName;
498 } 643 }
499 var isArray = typeMirror.isSubtypeOf(listMirror); 644 var isArray = typeMirror.isSubtypeOf(listMirror);
500 (isArray ? implementsArray : implements).add( 645 (isArray ? implementsArray : implements).add(
501 '${prefixName}.${mirrors.MirrorSystem.getName(typeMirror.simpleName)}'); 646 '${prefixName}.${mirrors.MirrorSystem.getName(typeMirror.simpleName)}');
502 } 647 }
503 libraryPrefixes.forEach((libraryMirror, prefix) { 648 libraryPrefixes.forEach((libraryMirror, prefix) {
504 sb.writeln('import "${libraryMirror.uri}" as $prefix;'); 649 sb.writeln('import "${libraryMirror.uri}" as $prefix;');
505 }); 650 });
506 buildImplementsClause(classes) => 651 buildImplementsClause(classes) =>
507 classes.isEmpty ? "" : "implements ${classes.join(', ')}" 652 classes.isEmpty ? "" : "implements ${classes.join(', ')}";
508 var implementsClause = buildImplementsClause(implements); 653 var implementsClause = buildImplementsClause(implements);
509 // TODO(jacobr): only certain classes need to be implemented by 654 // TODO(jacobr): only certain classes need to be implemented by
510 // JsFunctionImpl. 655 // JsFunctionImpl.
511 var allTypes = []..addAll(implements)..addAll(implementsArray); 656 var allTypes = []..addAll(implements)..addAll(implementsArray);
512 sb.write(''' 657 sb.write('''
513 class JsObjectImpl extends JsObject $implementsClause { 658 class JsObjectImpl extends JsObject $implementsClause {
514 JsObjectImpl.internal() : super.internal(); 659 JsObjectImpl.internal() : super.internal();
515 } 660 }
516 661
517 class JsFunctionImpl extends JsFunction $implementsClause { 662 class JsFunctionImpl extends JsFunction $implementsClause {
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
572 sep = ","; 717 sep = ",";
573 } 718 }
574 return list.map((e) => e == null ? "" : e.toString()).join(sep.toString()); 719 return list.map((e) => e == null ? "" : e.toString()).join(sep.toString());
575 } 720 }
576 721
577 // TODO(jacobr): should we really bother with this method instead of just 722 // TODO(jacobr): should we really bother with this method instead of just
578 // shallow copying to a JS array and using the toString method? 723 // shallow copying to a JS array and using the toString method?
579 String _arrayToString(List list) => _arrayJoin(list, ","); 724 String _arrayToString(List list) => _arrayJoin(list, ",");
580 725
581 int _arrayPush(List list, List args) { 726 int _arrayPush(List list, List args) {
582 for(var e in args) { 727 for (var e in args) {
583 list.add(e); 728 list.add(e);
584 } 729 }
585 return list.length; 730 return list.length;
586 } 731 }
587 732
588 _arrayPop(List list) { 733 _arrayPop(List list) {
589 if (list.length > 0) return list.removeLast(); 734 if (list.length > 0) return list.removeLast();
590 } 735 }
591 736
592 // TODO(jacobr): would it be better to just copy input to a JS List 737 // TODO(jacobr): would it be better to just copy input to a JS List
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
696 JsObject get context { 841 JsObject get context {
697 if (_cachedContext == null) { 842 if (_cachedContext == null) {
698 _cachedContext = _context; 843 _cachedContext = _context;
699 } 844 }
700 return _cachedContext; 845 return _cachedContext;
701 } 846 }
702 847
703 _maybeWrap(o) { 848 _maybeWrap(o) {
704 var wrapped = html_common.wrap_jso_no_SerializedScriptvalue(o); 849 var wrapped = html_common.wrap_jso_no_SerializedScriptvalue(o);
705 if (identical(wrapped, o)) return o; 850 if (identical(wrapped, o)) return o;
706 return (wrapped is html.Blob 851 return (wrapped is html.Blob ||
707 || wrapped is html.Event 852 wrapped is html.Event ||
708 || wrapped is indexed_db.KeyRange 853 wrapped is indexed_db.KeyRange ||
709 || wrapped is html.ImageData 854 wrapped is html.ImageData ||
710 || wrapped is html.Node 855 wrapped is html.Node ||
711 || wrapped is TypedData 856 wrapped is TypedData ||
712 || wrapped is html.Window) ? wrapped : o; 857 wrapped is html.Window) ? wrapped : o;
713 } 858 }
714 859
715 /** 860 /**
716 * Get the dart wrapper object for object. Top-level so we 861 * Get the dart wrapper object for object. Top-level so we
717 * we can access it from other libraries without it being 862 * we can access it from other libraries without it being
718 * a public instance field on JsObject. 863 * a public instance field on JsObject.
719 */ 864 */
720 @Deprecated("Internal Use Only") 865 @Deprecated("Internal Use Only")
721 getDartHtmlWrapperFor(JsObject object) => object._dartHtmlWrapper; 866 getDartHtmlWrapperFor(JsObject object) => object._dartHtmlWrapper;
722 867
723 /** 868 /**
724 * Set the dart wrapper object for object. Top-level so we 869 * Set the dart wrapper object for object. Top-level so we
725 * we can access it from other libraries without it being 870 * we can access it from other libraries without it being
726 * a public instance field on JsObject. 871 * a public instance field on JsObject.
727 */ 872 */
728 @Deprecated("Internal Use Only") 873 @Deprecated("Internal Use Only")
729 void setDartHtmlWrapperFor(JsObject object, wrapper) { 874 void setDartHtmlWrapperFor(JsObject object, wrapper) {
730 object._dartHtmlWrapper = wrapper; 875 object._dartHtmlWrapper = wrapper;
731 } 876 }
732 877
733 /** 878 /**
734 * Used by callMethod to get the JS object for each argument passed if the 879 * Used by callMethod to get the JS object for each argument passed if the
735 * argument is a Dart class instance that delegates to a DOM object. See 880 * argument is a Dart class instance that delegates to a DOM object. See
736 * wrap_jso defined in dart:html. 881 * wrap_jso defined in dart:html.
737 */ 882 */
738 @Deprecated("Internal Use Only") 883 @Deprecated("Internal Use Only")
739 unwrap_jso(dartClass_instance) { 884 unwrap_jso(dartClass_instance) {
740 if (dartClass_instance is html.DartHtmlDomObject) 885 if (dartClass_instance is html.DartHtmlDomObject &&
741 return dartClass_instance.blink_jsObject; 886 dartClass_instance is! JsObject) return dartClass_instance.blink_jsObject;
742 else 887 else return dartClass_instance;
743 return dartClass_instance;
744 } 888 }
745 889
746 /** 890 /**
747 * Proxies a JavaScript object to Dart. 891 * Proxies a JavaScript object to Dart.
748 * 892 *
749 * The properties of the JavaScript object are accessible via the `[]` and 893 * The properties of the JavaScript object are accessible via the `[]` and
750 * `[]=` operators. Methods are callable via [callMethod]. 894 * `[]=` operators. Methods are callable via [callMethod].
751 */ 895 */
752 class JsObject extends NativeFieldWrapperClass2 { 896 class JsObject extends NativeFieldWrapperClass2 {
753 JsObject.internal(); 897 JsObject.internal();
754 898
755 /** 899 /**
756 * If this JsObject is wrapped, e.g. DOM objects, then we can save the 900 * If this JsObject is wrapped, e.g. DOM objects, then we can save the
757 * wrapper here and preserve its identity. 901 * wrapper here and preserve its identity.
758 */ 902 */
759 var _dartHtmlWrapper; 903 var _dartHtmlWrapper;
760 904
761 /** 905 /**
762 * Constructs a new JavaScript object from [constructor] and returns a proxy 906 * Constructs a new JavaScript object from [constructor] and returns a proxy
763 * to it. 907 * to it.
764 */ 908 */
765 factory JsObject(JsFunction constructor, [List arguments]) { 909 factory JsObject(JsFunction constructor, [List arguments]) {
766 try { 910 try {
767 return _create(constructor, arguments); 911 return html_common.unwrap_jso(_create(constructor, arguments));
768 } catch (e) { 912 } catch (e) {
769 // Re-throw any errors (returned as a string) as a DomException. 913 // Re-throw any errors (returned as a string) as a DomException.
770 throw new html.DomException.jsInterop(e); 914 throw new html.DomException.jsInterop(e);
771 } 915 }
772 } 916 }
773 917
774 static JsObject _create( 918 static JsObject _create(JsFunction constructor, arguments)
775 JsFunction constructor, arguments) native "JsObject_constructorCallback"; 919 native "JsObject_constructorCallback";
776 920
777 _buildArgs(Invocation invocation) { 921 _buildArgs(Invocation invocation) {
778 if (invocation.namedArguments.isEmpty) { 922 if (invocation.namedArguments.isEmpty) {
779 return invocation.positionalArguments; 923 return invocation.positionalArguments;
780 } else { 924 } else {
781 var varArgs = new Map<String, Object>(); 925 var varArgs = new Map<String, Object>();
782 invocation.namedArguments.forEach((symbol, val) { 926 invocation.namedArguments.forEach((symbol, val) {
783 varArgs[mirrors.MirrorSystem.getName(symbol)] = val; 927 varArgs[mirrors.MirrorSystem.getName(symbol)] = val;
784 }); 928 });
785 return invocation.positionalArguments.toList() 929 return invocation.positionalArguments.toList()
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
832 * The type of [property] must be either [String] or [num]. 976 * The type of [property] must be either [String] or [num].
833 */ 977 */
834 operator [](property) { 978 operator [](property) {
835 try { 979 try {
836 return _maybeWrap(_operator_getter(property)); 980 return _maybeWrap(_operator_getter(property));
837 } catch (e) { 981 } catch (e) {
838 // Re-throw any errors (returned as a string) as a DomException. 982 // Re-throw any errors (returned as a string) as a DomException.
839 throw new html.DomException.jsInterop(e); 983 throw new html.DomException.jsInterop(e);
840 } 984 }
841 } 985 }
986
842 _operator_getter(property) native "JsObject_[]"; 987 _operator_getter(property) native "JsObject_[]";
843 988
844 /** 989 /**
845 * Sets the value associated with [property] on the proxied JavaScript 990 * Sets the value associated with [property] on the proxied JavaScript
846 * object. 991 * object.
847 * 992 *
848 * The type of [property] must be either [String] or [num]. 993 * The type of [property] must be either [String] or [num].
849 */ 994 */
850 operator []=(property, value) { 995 operator []=(property, value) {
851 try { 996 try {
852 _operator_setter(property, value); 997 _operator_setter(property, value);
853 } catch (e) { 998 } catch (e) {
854 // Re-throw any errors (returned as a string) as a DomException. 999 // Re-throw any errors (returned as a string) as a DomException.
855 throw new html.DomException.jsInterop(e); 1000 throw new html.DomException.jsInterop(e);
856 } 1001 }
857 } 1002 }
1003
858 _operator_setter(property, value) native "JsObject_[]="; 1004 _operator_setter(property, value) native "JsObject_[]=";
859 1005
860 int get hashCode native "JsObject_hashCode"; 1006 int get hashCode native "JsObject_hashCode";
861 1007
862 operator ==(other) { 1008 operator ==(other) {
863 var is_JsObject = other is JsObject; 1009 var is_JsObject = other is JsObject;
864 if (!is_JsObject) { 1010 if (!is_JsObject) {
865 other = html_common.unwrap_jso(other); 1011 other = html_common.unwrap_jso(other);
866 is_JsObject = other is JsObject; 1012 is_JsObject = other is JsObject;
867 } 1013 }
868 return is_JsObject && _identityEquality(this, other); 1014 return is_JsObject && _identityEquality(this, other);
869 } 1015 }
870 1016
871 static bool _identityEquality( 1017 static bool _identityEquality(JsObject a, JsObject b)
872 JsObject a, JsObject b) native "JsObject_identityEquality"; 1018 native "JsObject_identityEquality";
873 1019
874 /** 1020 /**
875 * Returns `true` if the JavaScript object contains the specified property 1021 * Returns `true` if the JavaScript object contains the specified property
876 * either directly or though its prototype chain. 1022 * either directly or though its prototype chain.
877 * 1023 *
878 * This is the equivalent of the `in` operator in JavaScript. 1024 * This is the equivalent of the `in` operator in JavaScript.
879 */ 1025 */
880 bool hasProperty(String property) native "JsObject_hasProperty"; 1026 bool hasProperty(String property) native "JsObject_hasProperty";
881 1027
882 /** 1028 /**
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
1012 * Returns a [JsFunction] that captures its 'this' binding and calls [f] 1158 * Returns a [JsFunction] that captures its 'this' binding and calls [f]
1013 * with the value of this passed as the first argument. 1159 * with the value of this passed as the first argument.
1014 */ 1160 */
1015 factory JsFunction.withThis(Function f) => _withThis(f); 1161 factory JsFunction.withThis(Function f) => _withThis(f);
1016 1162
1017 /** 1163 /**
1018 * Invokes the JavaScript function with arguments [args]. If [thisArg] is 1164 * Invokes the JavaScript function with arguments [args]. If [thisArg] is
1019 * supplied it is the value of `this` for the invocation. 1165 * supplied it is the value of `this` for the invocation.
1020 */ 1166 */
1021 dynamic apply(List args, {thisArg}) => 1167 dynamic apply(List args, {thisArg}) =>
1022 _maybeWrap(_apply(args, thisArg: thisArg)); 1168 _maybeWrap(_apply(args, thisArg: thisArg));
1023 1169
1024 dynamic _apply(List args, {thisArg}) native "JsFunction_apply"; 1170 dynamic _apply(List args, {thisArg}) native "JsFunction_apply";
1025 1171
1026 noSuchMethod(Invocation invocation) { 1172 noSuchMethod(Invocation invocation) {
1027 if (invocation.isMethod && invocation.memberName == #call) { 1173 if (invocation.isMethod && invocation.memberName == #call) {
1028 return apply(_buildArgs(invocation)); 1174 return apply(_buildArgs(invocation));
1029 } 1175 }
1030 return super.noSuchMethod(invocation); 1176 return super.noSuchMethod(invocation);
1031 } 1177 }
1032 1178
1033 /** 1179 /**
1034 * Internal only version of apply which uses debugger proxies of Dart objects 1180 * Internal only version of apply which uses debugger proxies of Dart objects
1035 * rather than opaque handles. This method is private because it cannot be 1181 * rather than opaque handles. This method is private because it cannot be
1036 * efficiently implemented in Dart2Js so should only be used by internal 1182 * efficiently implemented in Dart2Js so should only be used by internal
1037 * tools. 1183 * tools.
1038 */ 1184 */
1039 _applyDebuggerOnly(List args, 1185 _applyDebuggerOnly(List args, {thisArg})
1040 {thisArg}) native "JsFunction_applyDebuggerOnly"; 1186 native "JsFunction_applyDebuggerOnly";
1041 1187
1042 static JsFunction _withThis(Function f) native "JsFunction_withThis"; 1188 static JsFunction _withThis(Function f) native "JsFunction_withThis";
1043 } 1189 }
1044 1190
1045 /** 1191 /**
1046 * A [List] proxying a JavaScript Array. 1192 * A [List] proxying a JavaScript Array.
1047 */ 1193 */
1048 class JsArray<E> extends JsObject with ListMixin<E> { 1194 class JsArray<E> extends JsObject with ListMixin<E> {
1049 JsArray.internal() : super.internal(); 1195 JsArray.internal() : super.internal();
1050 1196
1051 factory JsArray() => _newJsArray(); 1197 factory JsArray() => _newJsArray();
1052 1198
1053 static JsArray _newJsArray() native "JsArray_newJsArray"; 1199 static JsArray _newJsArray() native "JsArray_newJsArray";
1054 1200
1055 factory JsArray.from(Iterable<E> other) => 1201 factory JsArray.from(Iterable<E> other) =>
1056 _newJsArrayFromSafeList(new List.from(other)); 1202 _newJsArrayFromSafeList(new List.from(other));
1057 1203
1058 static JsArray _newJsArrayFromSafeList( 1204 static JsArray _newJsArrayFromSafeList(List list)
1059 List list) native "JsArray_newJsArrayFromSafeList"; 1205 native "JsArray_newJsArrayFromSafeList";
1060 1206
1061 _checkIndex(int index, {bool insert: false}) { 1207 _checkIndex(int index, {bool insert: false}) {
1062 int length = insert ? this.length + 1 : this.length; 1208 int length = insert ? this.length + 1 : this.length;
1063 if (index is int && (index < 0 || index >= length)) { 1209 if (index is int && (index < 0 || index >= length)) {
1064 throw new RangeError.range(index, 0, length); 1210 throw new RangeError.range(index, 0, length);
1065 } 1211 }
1066 } 1212 }
1067 1213
1068 _checkRange(int start, int end) { 1214 _checkRange(int start, int end) {
1069 int cachedLength = this.length; 1215 int cachedLength = this.length;
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
1151 1297
1152 // TODO(jacobr): this method is a hack to work around the lack of proper dart 1298 // TODO(jacobr): this method is a hack to work around the lack of proper dart
1153 // support for varargs methods. 1299 // support for varargs methods.
1154 List _stripUndefinedArgs(List args) => 1300 List _stripUndefinedArgs(List args) =>
1155 args.takeWhile((i) => i != _UNDEFINED).toList(); 1301 args.takeWhile((i) => i != _UNDEFINED).toList();
1156 1302
1157 /** 1303 /**
1158 * Returns a method that can be called with an arbitrary number (for n less 1304 * Returns a method that can be called with an arbitrary number (for n less
1159 * than 11) of arguments without violating Dart type checks. 1305 * than 11) of arguments without violating Dart type checks.
1160 */ 1306 */
1161 Function _wrapAsDebuggerVarArgsFunction(JsFunction jsFunction) => 1307 Function _wrapAsDebuggerVarArgsFunction(JsFunction jsFunction) => (
1162 ([a1 = _UNDEFINED, a2 = _UNDEFINED, a3 = _UNDEFINED, a4 = _UNDEFINED, 1308 [a1 = _UNDEFINED,
1163 a5 = _UNDEFINED, a6 = _UNDEFINED, a7 = _UNDEFINED, a8 = _UNDEFINED, 1309 a2 = _UNDEFINED,
1164 a9 = _UNDEFINED, a10 = _UNDEFINED]) => jsFunction._applyDebuggerOnly( 1310 a3 = _UNDEFINED,
1165 _stripUndefinedArgs([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10])); 1311 a4 = _UNDEFINED,
1312 a5 = _UNDEFINED,
1313 a6 = _UNDEFINED,
1314 a7 = _UNDEFINED,
1315 a8 = _UNDEFINED,
1316 a9 = _UNDEFINED,
1317 a10 = _UNDEFINED]) =>
1318 jsFunction._applyDebuggerOnly(
1319 _stripUndefinedArgs([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10]));
1166 1320
1167 // The allowInterop method is a no-op in Dartium. 1321 // The allowInterop method is a no-op in Dartium.
1168 // TODO(jacobr): tag methods so we can throw if a Dart method is passed to 1322 // TODO(jacobr): tag methods so we can throw if a Dart method is passed to
1169 // JavaScript using the new interop without calling allowInterop. 1323 // JavaScript using the new interop without calling allowInterop.
1170 1324
1171 /// Returns a wrapper around function [f] that can be called from JavaScript 1325 /// Returns a wrapper around function [f] that can be called from JavaScript
1172 /// using the package:js Dart-JavaScript interop. 1326 /// using the package:js Dart-JavaScript interop.
1173 /// 1327 ///
1174 /// For performance reasons in Dart2Js, by default Dart functions cannot be 1328 /// For performance reasons in Dart2Js, by default Dart functions cannot be
1175 /// passed directly to JavaScript unless this method is called to create 1329 /// passed directly to JavaScript unless this method is called to create
(...skipping 21 matching lines...) Expand all
1197 return f; 1351 return f;
1198 } else { 1352 } else {
1199 var ret = _interopCaptureThisExpando[f]; 1353 var ret = _interopCaptureThisExpando[f];
1200 if (ret == null) { 1354 if (ret == null) {
1201 ret = new JsFunction.withThis(f); 1355 ret = new JsFunction.withThis(f);
1202 _interopCaptureThisExpando[f] = ret; 1356 _interopCaptureThisExpando[f] = ret;
1203 } 1357 }
1204 return ret; 1358 return ret;
1205 } 1359 }
1206 } 1360 }
OLDNEW
« runtime/lib/mirrors.cc ('K') | « runtime/lib/mirrors_impl.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698