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

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

Issue 2158493003: Utility class of static methods to efficiently manipulate typed JSInterop objects in a dynamic mann… (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 5 months 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
« no previous file with comments | « no previous file | 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 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
99 import 'dart:core'; 99 import 'dart:core';
100 100
101 import 'cached_patches.dart'; 101 import 'cached_patches.dart';
102 102
103 // Pretend we are always in checked mode as we aren't interested in users 103 // Pretend we are always in checked mode as we aren't interested in users
104 // running Dartium code outside of checked mode. 104 // running Dartium code outside of checked mode.
105 @Deprecated("Internal Use Only") 105 @Deprecated("Internal Use Only")
106 final bool CHECK_JS_INVOCATIONS = true; 106 final bool CHECK_JS_INVOCATIONS = true;
107 107
108 final String _DART_RESERVED_NAME_PREFIX = r'JS$'; 108 final String _DART_RESERVED_NAME_PREFIX = r'JS$';
109 // If a private class is defined to use @JS we need to inject a non-private
110 // class with a name that will not cause collisions in the library so we can
111 // make JSObject implement that interface even though it is in a different
112 // library.
113 final String escapePrivateClassPrefix = r'$JSImplClass23402893498';
Alan Knight 2016/07/19 16:56:16 Is this a problem if there are two different priva
Jacob 2016/07/19 17:36:40 No because all libraries are imported into the dar
109 114
110 String _stripReservedNamePrefix(String name) => 115 String _stripReservedNamePrefix(String name) =>
111 name.startsWith(_DART_RESERVED_NAME_PREFIX) 116 name.startsWith(_DART_RESERVED_NAME_PREFIX)
112 ? name.substring(_DART_RESERVED_NAME_PREFIX.length) 117 ? name.substring(_DART_RESERVED_NAME_PREFIX.length)
113 : name; 118 : name;
114 119
115 _buildArgs(Invocation invocation) { 120 _buildArgs(Invocation invocation) {
116 if (invocation.namedArguments.isEmpty) { 121 if (invocation.namedArguments.isEmpty) {
117 return invocation.positionalArguments; 122 return invocation.positionalArguments;
118 } else { 123 } else {
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
333 // is file://dart/sdk/lib/html/html_common/metadata.dart 338 // is file://dart/sdk/lib/html/html_common/metadata.dart
334 // instead of a proper dart: location. 339 // instead of a proper dart: location.
335 return true; 340 return true;
336 } 341 }
337 } 342 }
338 return false; 343 return false;
339 } 344 }
340 345
341 _getJsMemberName(mirrors.DeclarationMirror mirror) { 346 _getJsMemberName(mirrors.DeclarationMirror mirror) {
342 var name = _getJsName(mirror); 347 var name = _getJsName(mirror);
343 return name == null || name.isEmpty ? _getDeclarationName(mirror) : name; 348 return name == null || name.isEmpty ? _stripReservedNamePrefix(_getDeclaration Name(mirror)) : name;
344 } 349 }
345 350
346 // TODO(jacobr): handle setters correctyl. 351 // TODO(jacobr): handle setters correctyl.
347 String _getDeclarationName(mirrors.DeclarationMirror declaration) { 352 String _getDeclarationName(mirrors.DeclarationMirror declaration) {
348 var name = mirrors.MirrorSystem.getName(declaration.simpleName); 353 var name = mirrors.MirrorSystem.getName(declaration.simpleName);
349 if (declaration is mirrors.MethodMirror && declaration.isSetter) { 354 if (declaration is mirrors.MethodMirror && declaration.isSetter) {
350 assert(name.endsWith("=")); 355 assert(name.endsWith("="));
351 name = name.substring(0, name.length - 1); 356 name = name.substring(0, name.length - 1);
352 } 357 }
353 return _stripReservedNamePrefix(name); 358 return name;
354 } 359 }
355 360
356 final _JS_LIBRARY_PREFIX = "js_library"; 361 final _JS_LIBRARY_PREFIX = "js_library";
357 final _UNDEFINED_VAR = "_UNDEFINED_JS_CONST"; 362 final _UNDEFINED_VAR = "_UNDEFINED_JS_CONST";
358 363
359 String _accessJsPath(String path) => _accessJsPathHelper(path.split(".")); 364 String _accessJsPath(String path) => _accessJsPathHelper(path.split("."));
360 365
361 String _accessJsPathHelper(Iterable<String> parts) { 366 String _accessJsPathHelper(Iterable<String> parts) {
362 var sb = new StringBuffer(); 367 var sb = new StringBuffer();
363 sb 368 sb
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
517 _isExternal(declaration)) { 522 _isExternal(declaration)) {
518 addMemberHelper(declaration, jsLibraryName, sb); 523 addMemberHelper(declaration, jsLibraryName, sb);
519 } 524 }
520 } else if (declaration is mirrors.ClassMirror) { 525 } else if (declaration is mirrors.ClassMirror) {
521 mirrors.ClassMirror clazz = declaration; 526 mirrors.ClassMirror clazz = declaration;
522 var isDom = dartLibrary ? hasDomName(clazz) : false; 527 var isDom = dartLibrary ? hasDomName(clazz) : false;
523 var isJsInterop = _hasJsName(clazz); 528 var isJsInterop = _hasJsName(clazz);
524 if (isDom || isJsInterop) { 529 if (isDom || isJsInterop) {
525 // TODO(jacobr): verify class implements JavaScriptObject. 530 // TODO(jacobr): verify class implements JavaScriptObject.
526 var className = mirrors.MirrorSystem.getName(clazz.simpleName); 531 var className = mirrors.MirrorSystem.getName(clazz.simpleName);
532 bool isPrivate = className.startsWith('_');
527 var classNameImpl = '${className}Impl'; 533 var classNameImpl = '${className}Impl';
528 var sbPatch = new StringBuffer(); 534 var sbPatch = new StringBuffer();
529 if (isJsInterop) { 535 if (isJsInterop) {
530 String jsClassName = _getJsMemberName(clazz); 536 String jsClassName = _getJsMemberName(clazz);
531 537
532 jsInterfaceTypes.add(clazz); 538 jsInterfaceTypes.add(clazz);
533 clazz.declarations.forEach((name, declaration) { 539 clazz.declarations.forEach((name, declaration) {
534 if (declaration is! mirrors.MethodMirror || 540 if (declaration is! mirrors.MethodMirror ||
535 !_isExternal(declaration)) return; 541 !_isExternal(declaration)) return;
536 if (declaration.isFactoryConstructor && 542 if (declaration.isFactoryConstructor &&
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
591 ? "${jsLibraryName}.${jsClassName}" 597 ? "${jsLibraryName}.${jsClassName}"
592 : jsClassName, 598 : jsClassName,
593 sbPatch, 599 sbPatch,
594 isStatic: true); 600 isStatic: true);
595 } 601 }
596 }); 602 });
597 } 603 }
598 if (isDom) { 604 if (isDom) {
599 sbPatch.write(" static Type get instanceRuntimeType => ${classNameI mpl};\n"); 605 sbPatch.write(" static Type get instanceRuntimeType => ${classNameI mpl};\n");
600 } 606 }
607 if (isPrivate) {
608 sb.write("""
609 class ${escapePrivateClassPrefix}${className} implements $className {}
610 """);
611 }
612
601 if (sbPatch.isNotEmpty) { 613 if (sbPatch.isNotEmpty) {
602 var typeVariablesClause = ''; 614 var typeVariablesClause = '';
603 if (!clazz.typeVariables.isEmpty) { 615 if (!clazz.typeVariables.isEmpty) {
604 typeVariablesClause = 616 typeVariablesClause =
605 '<${clazz.typeVariables.map((m) => mirrors.MirrorSystem.getNam e(m.simpleName)).join(',')}>'; 617 '<${clazz.typeVariables.map((m) => mirrors.MirrorSystem.getNam e(m.simpleName)).join(',')}>';
606 } 618 }
607 sb.write(""" 619 sb.write("""
608 patch class $className$typeVariablesClause { 620 patch class $className$typeVariablesClause {
609 $sbPatch 621 $sbPatch
610 } 622 }
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
698 while (prefixNames.contains(prefixName)) { 710 while (prefixNames.contains(prefixName)) {
699 prefixName = '$basePrefixName$i'; 711 prefixName = '$basePrefixName$i';
700 i++; 712 i++;
701 } 713 }
702 prefixNames.add(prefixName); 714 prefixNames.add(prefixName);
703 libraryPrefixes[libraryMirror] = prefixName; 715 libraryPrefixes[libraryMirror] = prefixName;
704 } 716 }
705 var isArray = typeMirror.isSubtypeOf(listMirror); 717 var isArray = typeMirror.isSubtypeOf(listMirror);
706 var isFunction = typeMirror.isSubtypeOf(functionMirror); 718 var isFunction = typeMirror.isSubtypeOf(functionMirror);
707 var isJSObject = typeMirror.isSubtypeOf(jsObjectMirror); 719 var isJSObject = typeMirror.isSubtypeOf(jsObjectMirror);
720 var className = mirrors.MirrorSystem.getName(typeMirror.simpleName);
721 var isPrivate = className.startsWith('_');
722 if (isPrivate) className = '${escapePrivateClassPrefix}${className}';
708 var fullName = 723 var fullName =
709 '${prefixName}.${mirrors.MirrorSystem.getName(typeMirror.simpleName)}'; 724 '${prefixName}.${className}';
710 (isArray ? implementsArray : implements).add(fullName); 725 (isArray ? implementsArray : implements).add(fullName);
711 if (!isArray && !isFunction && !isJSObject) { 726 if (!isArray && !isFunction && !isJSObject) {
712 // For DOM classes we need to be a bit more conservative at tagging them 727 // For DOM classes we need to be a bit more conservative at tagging them
713 // as implementing JS inteorp classes risks strange unintended 728 // as implementing JS inteorp classes risks strange unintended
714 // consequences as unrleated code may have instanceof checks. Checking 729 // consequences as unrleated code may have instanceof checks. Checking
715 // for isJSObject ensures we do not accidentally pull in existing 730 // for isJSObject ensures we do not accidentally pull in existing
716 // dart:html classes as they all have JSObject as a base class. 731 // dart:html classes as they all have JSObject as a base class.
717 // Note that methods from these classes can still be called on a 732 // Note that methods from these classes can still be called on a
718 // dart:html instance but checked mode type checks will fail. This is 733 // dart:html instance but checked mode type checks will fail. This is
719 // not ideal but is better than causing strange breaks in existing 734 // not ideal but is better than causing strange breaks in existing
(...skipping 602 matching lines...) Expand 10 before | Expand all | Expand 10 after
1322 1337
1323 static toTypedObject(JsObject o) native "JSNative_toTypedObject"; 1338 static toTypedObject(JsObject o) native "JSNative_toTypedObject";
1324 1339
1325 /** 1340 /**
1326 * Same behavior as new JsFunction.withThis except that JavaScript "this" is n ot 1341 * Same behavior as new JsFunction.withThis except that JavaScript "this" is n ot
1327 * wrapped. 1342 * wrapped.
1328 */ 1343 */
1329 static JSFunction withThis(Function f) native "JsFunction_withThisNoWrap"; 1344 static JSFunction withThis(Function f) native "JsFunction_withThisNoWrap";
1330 } 1345 }
1331 1346
1347 /// Utility methods to efficiently manipulate typed JSInterop objects in cases
1348 /// where the name to call is not known at runtime. You should only use these
1349 /// methods when the same effect cannot be achieved with @JS annotations.
1350 /// These methods would be extension methods on JSObject if Dart supported
1351 /// extension methods.
1352 class JSNative {
1353 /**
1354 * WARNING: performance of this method is much worse than other methods
1355 * in JSNative. Only use this method as a last resort.
1356 *
1357 * Recursively converts a JSON-like collection of Dart objects to a
1358 * collection of JavaScript objects and returns a [JsObject] proxy to it.
1359 *
1360 * [object] must be a [Map] or [Iterable], the contents of which are also
1361 * converted. Maps and Iterables are copied to a new JavaScript object.
1362 * Primitives and other transferrable values are directly converted to their
1363 * JavaScript type, and all other objects are proxied.
1364 */
1365 static jsify(object) {
1366 if ((object is! Map) && (object is! Iterable)) {
1367 throw new ArgumentError("object must be a Map or Iterable");
1368 }
1369 return _jsify(object);
1370 }
1371
1372 static _jsify(object) native "JSObject_jsify";
1373 static JSObject newObject() native "JSObject_newObject";
1374
1375 static hasProperty(JSObject o, name) => o._hasProperty(name);
1376 static getProperty(JSObject o, name) => o._operator_getter(name);
1377 static setProperty(JSObject o, name, value) => o._operator_setter(name, value) ;
1378 static callMethod(JSObject o, String method, List args) => o._callMethod(metho d, args);
1379 static instanceof(JSObject o, Function type) => o._instanceof(type);
1380 static callConstructor(JSObject constructor, List args) native "JSNative_callC onstructor";
1381 }
1332 1382
1333 /** 1383 /**
1334 * Proxies a JavaScript Function object. 1384 * Proxies a JavaScript Function object.
1335 */ 1385 */
1336 class JsFunction extends JsObject { 1386 class JsFunction extends JsObject {
1337 JsFunction.internal() : super.internal(); 1387 JsFunction.internal() : super.internal();
1338 1388
1339 /** 1389 /**
1340 * Returns a [JsFunction] that captures its 'this' binding and calls [f] 1390 * Returns a [JsFunction] that captures its 'this' binding and calls [f]
1341 * with the value of this passed as the first argument. 1391 * with the value of this passed as the first argument.
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
1556 } else { 1606 } else {
1557 var ret = _interopCaptureThisExpando[f]; 1607 var ret = _interopCaptureThisExpando[f];
1558 if (ret == null) { 1608 if (ret == null) {
1559 // TODO(jacobr): we could optimize this. 1609 // TODO(jacobr): we could optimize this.
1560 ret = JSFunction._createWithThis(f); 1610 ret = JSFunction._createWithThis(f);
1561 _interopCaptureThisExpando[f] = ret; 1611 _interopCaptureThisExpando[f] = ret;
1562 } 1612 }
1563 return ret; 1613 return ret;
1564 } 1614 }
1565 } 1615 }
1566
1567 debugPrint(_) {}
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698