OLD | NEW |
---|---|
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 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
88 library dart.js; | 88 library dart.js; |
89 | 89 |
90 import 'dart:collection' show ListMixin; | 90 import 'dart:collection' show ListMixin; |
91 import 'dart:nativewrappers'; | 91 import 'dart:nativewrappers'; |
92 import 'dart:math' as math; | 92 import 'dart:math' as math; |
93 import 'dart:mirrors' as mirrors; | 93 import 'dart:mirrors' as mirrors; |
94 import 'dart:html' as html; | 94 import 'dart:html' as html; |
95 import 'dart:html_common' as html_common; | 95 import 'dart:html_common' as html_common; |
96 import 'dart:indexed_db' as indexed_db; | 96 import 'dart:indexed_db' as indexed_db; |
97 import 'dart:typed_data'; | 97 import 'dart:typed_data'; |
98 import 'dart:core'; | |
99 | |
100 import 'cached_patches.dart'; | |
98 | 101 |
99 // Pretend we are always in checked mode as we aren't interested in users | 102 // Pretend we are always in checked mode as we aren't interested in users |
100 // running Dartium code outside of checked mode. | 103 // running Dartium code outside of checked mode. |
101 @Deprecated("Internal Use Only") | 104 @Deprecated("Internal Use Only") |
102 final bool CHECK_JS_INVOCATIONS = true; | 105 final bool CHECK_JS_INVOCATIONS = true; |
103 | 106 |
104 final String _DART_RESERVED_NAME_PREFIX = r'JS$'; | 107 final String _DART_RESERVED_NAME_PREFIX = r'JS$'; |
105 | 108 |
106 String _stripReservedNamePrefix(String name) => | 109 String _stripReservedNamePrefix(String name) => |
107 name.startsWith(_DART_RESERVED_NAME_PREFIX) | 110 name.startsWith(_DART_RESERVED_NAME_PREFIX) |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
271 .putIfAbsent(symbol, () => new _DeclarationSet()) | 274 .putIfAbsent(symbol, () => new _DeclarationSet()) |
272 .add(declaration); | 275 .add(declaration); |
273 } | 276 } |
274 } | 277 } |
275 }); | 278 }); |
276 } | 279 } |
277 } | 280 } |
278 | 281 |
279 _finalizeJsInterfaces() native "Js_finalizeJsInterfaces"; | 282 _finalizeJsInterfaces() native "Js_finalizeJsInterfaces"; |
280 | 283 |
284 // Create the files for the generated Dart files from IDLs. These only change | |
285 // when browser's Dart files change (dart:*). | |
286 String createCachedPatchesFile() { | |
Jacob
2016/03/28 14:23:58
can you keep this method out of dart:js which is a
terry
2016/03/28 14:45:31
Added @Deprecated("Internal Use Only")
Done.
| |
287 var patches = _generateInteropPatchFiles(['dart:html', | |
288 'dart:indexed_db', | |
289 'dart:web_gl', | |
290 'dart:web_sql', | |
291 'dart:svg', | |
292 'dart:web_audio']); | |
293 var sb = new StringBuffer(); | |
294 | |
295 sb.write(""" | |
296 | |
297 // START_OF_CACHED_PATCHES | |
298 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | |
299 // for details. All rights reserved. Use of this source code is governed by a | |
300 // BSD-style license that can be found in the LICENSE file. | |
301 | |
302 // DO NOT EDIT GENERATED FILE. | |
303 | |
304 library cached_patches; | |
305 | |
306 var cached_patches = {"""); | |
307 | |
308 for (var baseIndex = 0; baseIndex < patches.length; baseIndex += 3) { | |
309 var uri = patches[baseIndex + 0]; | |
310 var uri_js_interop = patches[baseIndex + 1]; | |
311 var source = patches[baseIndex + 2]; | |
312 | |
313 if (uri != 'dart:js') { | |
314 sb.write('"$uri": ["$uri", "$uri_js_interop", """$source"""],'); | |
315 } | |
316 } | |
317 | |
318 sb.write("""}; | |
319 // END_OF_CACHED_PATCHES | |
320 """); | |
321 | |
322 return "$sb"; | |
323 } | |
324 | |
281 String _getJsName(mirrors.DeclarationMirror mirror) { | 325 String _getJsName(mirrors.DeclarationMirror mirror) { |
282 for (var annotation in mirror.metadata) { | 326 if (_atJsType != null) { |
283 if (mirrors.MirrorSystem.getName(annotation.type.simpleName) == "JS") { | 327 for (var annotation in mirror.metadata) { |
284 mirrors.LibraryMirror library = annotation.type.owner; | 328 if (annotation.type.reflectedType == _atJsType) { |
285 var uri = library.uri; | |
286 // make sure the annotation is from package://js | |
287 if (uri.scheme == 'package' && uri.path == 'js/js.dart') { | |
288 try { | 329 try { |
289 var name = annotation.reflectee.name; | 330 var name = annotation.reflectee.name; |
290 return name != null ? name : ""; | 331 return name != null ? name : ""; |
291 } catch (e) {} | 332 } catch (e) {} |
292 } | 333 } |
293 } | 334 } |
294 } | 335 } |
295 return null; | 336 return null; |
296 } | 337 } |
297 | 338 |
298 bool _isAnonymousClass(mirrors.ClassMirror mirror) { | 339 bool _isAnonymousClass(mirrors.ClassMirror mirror) { |
299 for (var annotation in mirror.metadata) { | 340 for (var annotation in mirror.metadata) { |
300 if (mirrors.MirrorSystem.getName(annotation.type.simpleName) == | 341 if (mirrors.MirrorSystem.getName(annotation.type.simpleName) == |
301 "_Anonymous") { | 342 "_Anonymous") { |
302 mirrors.LibraryMirror library = annotation.type.owner; | 343 mirrors.LibraryMirror library = annotation.type.owner; |
303 var uri = library.uri; | 344 var uri = library.uri; |
304 // make sure the annotation is from package://js | 345 // make sure the annotation is from package://js |
305 if (uri.scheme == 'package' && uri.path == 'js/js.dart') { | 346 if (uri.scheme == 'package' && uri.path == 'js/js.dart') { |
306 return true; | 347 return true; |
307 } | 348 } |
308 } | 349 } |
309 } | 350 } |
310 return false; | 351 return false; |
311 } | 352 } |
312 | 353 |
313 bool _hasJsName(mirrors.DeclarationMirror mirror) => _getJsName(mirror) != null; | 354 bool _hasJsName(mirrors.DeclarationMirror mirror) => _getJsName(mirror) != null; |
314 | 355 |
356 var _domNameType; | |
357 | |
315 bool hasDomName(mirrors.DeclarationMirror mirror) { | 358 bool hasDomName(mirrors.DeclarationMirror mirror) { |
316 var location = mirror.location; | 359 var location = mirror.location; |
317 if (location == null || location.sourceUri.scheme != 'dart') return false; | 360 if (location == null || location.sourceUri.scheme != 'dart') return false; |
318 for (var annotation in mirror.metadata) { | 361 for (var annotation in mirror.metadata) { |
319 if (mirrors.MirrorSystem.getName(annotation.type.simpleName) == "DomName") { | 362 if (mirrors.MirrorSystem.getName(annotation.type.simpleName) == "DomName") { |
320 // We can't make sure the annotation is in dart: as Dartium believes it | 363 // We can't make sure the annotation is in dart: as Dartium believes it |
321 // is file://dart/sdk/lib/html/html_common/metadata.dart | 364 // is file://dart/sdk/lib/html/html_common/metadata.dart |
322 // instead of a proper dart: location. | 365 // instead of a proper dart: location. |
323 return true; | 366 return true; |
324 } | 367 } |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
438 } | 481 } |
439 | 482 |
440 bool _isExternal(mirrors.MethodMirror mirror) { | 483 bool _isExternal(mirrors.MethodMirror mirror) { |
441 // This try-catch block is a workaround for BUG:24834. | 484 // This try-catch block is a workaround for BUG:24834. |
442 try { | 485 try { |
443 return mirror.isExternal; | 486 return mirror.isExternal; |
444 } catch (e) {} | 487 } catch (e) {} |
445 return false; | 488 return false; |
446 } | 489 } |
447 | 490 |
448 List<String> _generateExternalMethods() { | 491 List<String> _generateExternalMethods(List<String> libraryPaths) { |
449 var staticCodegen = <String>[]; | 492 var staticCodegen = <String>[]; |
450 mirrors.currentMirrorSystem().libraries.forEach((uri, library) { | 493 |
494 if (libraryPaths.length == 0) { | |
495 mirrors.currentMirrorSystem().libraries.forEach((uri, library) { | |
496 var library_name = "${uri.scheme}:${uri.path}"; | |
497 if (cached_patches.containsKey(library_name)) { | |
498 var patch = cached_patches[library_name]; | |
499 staticCodegen.addAll(patch); | |
500 } else { | |
501 _generateLibraryCodegen(uri, library, staticCodegen); | |
502 } | |
503 }); // End of library foreach | |
504 } else { | |
505 // Used to generate cached_patches.dart file for all IDL generated dart: | |
506 // files to the WebKit DOM. | |
507 for (var library_name in libraryPaths) { | |
508 var parts = library_name.split(':'); | |
509 var uri = new Uri(scheme: parts[0], path: parts[1]); | |
510 var library = mirrors.currentMirrorSystem().libraries[uri]; | |
511 _generateLibraryCodegen(uri, library, staticCodegen); | |
512 } | |
513 } | |
514 | |
515 return staticCodegen; | |
516 } | |
517 | |
518 _generateLibraryCodegen(uri, library, staticCodegen) { | |
519 // Is it a dart generated library? | |
520 var dartLibrary = uri.scheme == 'dart'; | |
521 | |
451 var sb = new StringBuffer(); | 522 var sb = new StringBuffer(); |
452 String jsLibraryName = _getJsName(library); | 523 String jsLibraryName = _getJsName(library); |
453 library.declarations.forEach((name, declaration) { | 524 library.declarations.forEach((name, declaration) { |
454 if (declaration is mirrors.MethodMirror) { | 525 if (declaration is mirrors.MethodMirror) { |
455 if ((_hasJsName(declaration) || jsLibraryName != null) && | 526 if ((_hasJsName(declaration) || jsLibraryName != null) && |
456 _isExternal(declaration)) { | 527 _isExternal(declaration)) { |
457 addMemberHelper(declaration, jsLibraryName, sb); | 528 addMemberHelper(declaration, jsLibraryName, sb); |
458 } | 529 } |
459 } else if (declaration is mirrors.ClassMirror) { | 530 } else if (declaration is mirrors.ClassMirror) { |
460 mirrors.ClassMirror clazz = declaration; | 531 mirrors.ClassMirror clazz = declaration; |
461 var isDom = hasDomName(clazz); | 532 var isDom = dartLibrary ? hasDomName(clazz) : false; |
462 var isJsInterop = _hasJsName(clazz); | 533 var isJsInterop = _hasJsName(clazz); |
463 if (isDom || isJsInterop) { | 534 if (isDom || isJsInterop) { |
464 // TODO(jacobr): verify class implements JavaScriptObject. | 535 // TODO(jacobr): verify class implements JavaScriptObject. |
465 var className = mirrors.MirrorSystem.getName(clazz.simpleName); | 536 var className = mirrors.MirrorSystem.getName(clazz.simpleName); |
466 var classNameImpl = '${className}Impl'; | 537 var classNameImpl = '${className}Impl'; |
467 var sbPatch = new StringBuffer(); | 538 var sbPatch = new StringBuffer(); |
468 if (isJsInterop) { | 539 if (isJsInterop) { |
469 String jsClassName = _getJsMemberName(clazz); | 540 String jsClassName = _getJsMemberName(clazz); |
470 | 541 |
471 jsInterfaceTypes.add(clazz); | 542 jsInterfaceTypes.add(clazz); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
512 sbPatch.write(" "); | 583 sbPatch.write(" "); |
513 addMemberHelper( | 584 addMemberHelper( |
514 declaration, | 585 declaration, |
515 (jsLibraryName != null && jsLibraryName.isNotEmpty) | 586 (jsLibraryName != null && jsLibraryName.isNotEmpty) |
516 ? "${jsLibraryName}.${jsClassName}" | 587 ? "${jsLibraryName}.${jsClassName}" |
517 : jsClassName, | 588 : jsClassName, |
518 sbPatch, | 589 sbPatch, |
519 isStatic: true, | 590 isStatic: true, |
520 memberName: className); | 591 memberName: className); |
521 } | 592 } |
522 }); | 593 }); // End of clazz.declarations.forEach |
523 | 594 |
524 clazz.staticMembers.forEach((memberName, member) { | 595 clazz.staticMembers.forEach((memberName, member) { |
525 if (_isExternal(member)) { | 596 if (_isExternal(member)) { |
526 sbPatch.write(" "); | 597 sbPatch.write(" "); |
527 addMemberHelper( | 598 addMemberHelper( |
528 member, | 599 member, |
529 (jsLibraryName != null && jsLibraryName.isNotEmpty) | 600 (jsLibraryName != null && jsLibraryName.isNotEmpty) |
530 ? "${jsLibraryName}.${jsClassName}" | 601 ? "${jsLibraryName}.${jsClassName}" |
531 : jsClassName, | 602 : jsClassName, |
532 sbPatch, | 603 sbPatch, |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
571 | 642 |
572 /** | 643 /** |
573 * Placeholder object for cases where we need to determine exactly how many | 644 * Placeholder object for cases where we need to determine exactly how many |
574 * args were passed to a function. | 645 * args were passed to a function. |
575 */ | 646 */ |
576 const ${_UNDEFINED_VAR} = const Object(); | 647 const ${_UNDEFINED_VAR} = const Object(); |
577 | 648 |
578 ${sb} | 649 ${sb} |
579 """); | 650 """); |
580 } | 651 } |
581 }); | 652 } |
582 | 653 |
583 return staticCodegen; | 654 // Remember the @JS type to compare annotation type. |
584 } | 655 var _atJsType = -1; |
585 | 656 |
586 /** | 657 /** |
587 * Generates part files defining source code for JSObjectImpl, all DOM classes | 658 * Generates part files defining source code for JSObjectImpl, all DOM classes |
588 * classes. This codegen is needed so that type checks for all registered | 659 * classes. This codegen is needed so that type checks for all registered |
589 * JavaScript interop classes pass. | 660 * JavaScript interop classes pass. |
590 */ | 661 */ |
591 List<String> _generateInteropPatchFiles() { | 662 List<String> _generateInteropPatchFiles(List<String> libraryPaths) { |
592 var ret = _generateExternalMethods(); | 663 // Cache the @JS Type. |
664 if (_atJsType == -1) { | |
665 var uri = new Uri(scheme: "package", path: "js/js.dart"); | |
666 var jsLibrary = mirrors.currentMirrorSystem().libraries[uri]; | |
667 if (jsLibrary != null) { | |
668 // @ JS used somewhere. | |
669 var jsDeclaration = jsLibrary.declarations[new Symbol("JS")]; | |
670 _atJsType = jsDeclaration.reflectedType; | |
671 } else { | |
672 // @ JS not used in any library. | |
673 _atJsType = null; | |
674 } | |
675 } | |
676 | |
677 var ret = _generateExternalMethods(libraryPaths); | |
593 var libraryPrefixes = new Map<mirrors.LibraryMirror, String>(); | 678 var libraryPrefixes = new Map<mirrors.LibraryMirror, String>(); |
594 var prefixNames = new Set<String>(); | 679 var prefixNames = new Set<String>(); |
595 var sb = new StringBuffer(); | 680 var sb = new StringBuffer(); |
596 | 681 |
597 var implements = <String>[]; | 682 var implements = <String>[]; |
598 var implementsArray = <String>[]; | 683 var implementsArray = <String>[]; |
599 var implementsDom = <String>[]; | 684 var implementsDom = <String>[]; |
600 var listMirror = mirrors.reflectType(List); | 685 var listMirror = mirrors.reflectType(List); |
601 var functionMirror = mirrors.reflectType(Function); | 686 var functionMirror = mirrors.reflectType(Function); |
602 var jsObjectMirror = mirrors.reflectType(JSObject); | 687 var jsObjectMirror = mirrors.reflectType(JSObject); |
(...skipping 957 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1560 var ret = _interopCaptureThisExpando[f]; | 1645 var ret = _interopCaptureThisExpando[f]; |
1561 if (ret == null) { | 1646 if (ret == null) { |
1562 // TODO(jacobr): we could optimize this. | 1647 // TODO(jacobr): we could optimize this. |
1563 ret = new JSFunction.create( | 1648 ret = new JSFunction.create( |
1564 new JsFunction.withThis(new _CreateDartFunctionForInterop(f))); | 1649 new JsFunction.withThis(new _CreateDartFunctionForInterop(f))); |
1565 _interopCaptureThisExpando[f] = ret; | 1650 _interopCaptureThisExpando[f] = ret; |
1566 } | 1651 } |
1567 return ret; | 1652 return ret; |
1568 } | 1653 } |
1569 } | 1654 } |
OLD | NEW |