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

Side by Side Diff: sdk/lib/js/dart2js/js_dart2js.dart

Issue 2150313003: Add JSNative utility class with static methods methods to efficiently manipulate typed JSInterop ob… (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Add JSNative utility class with static methods methods to efficiently manipulate typed JSInterop ob… 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
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 689 matching lines...) Expand 10 before | Expand all | Expand 10 after
700 } 700 }
701 701
702 _callDartFunctionFast(callback, List arguments) { 702 _callDartFunctionFast(callback, List arguments) {
703 return Function.apply(callback, arguments); 703 return Function.apply(callback, arguments);
704 } 704 }
705 705
706 _callDartFunctionFastCaptureThis(callback, self, List arguments) { 706 _callDartFunctionFastCaptureThis(callback, self, List arguments) {
707 return Function.apply(callback, [self]..addAll(arguments)); 707 return Function.apply(callback, [self]..addAll(arguments));
708 } 708 }
709 709
710 Function /*=F*/ allowInterop/*<F extends Function>*/(Function /*=F*/ f) { 710 Function/*=F*/ allowInterop/*<F extends Function>*/(Function/*=F*/ f) {
711 if (JS('bool', 'typeof(#) == "function"', f)) { 711 if (JS('bool', 'typeof(#) == "function"', f)) {
712 // Already supports interop, just use the existing function. 712 // Already supports interop, just use the existing function.
713 return f; 713 return f;
714 } else { 714 } else {
715 return _convertDartFunctionFast(f); 715 return _convertDartFunctionFast(f);
716 } 716 }
717 } 717 }
718 718
719 Function allowInteropCaptureThis(Function f) { 719 Function allowInteropCaptureThis(Function f) {
720 if (JS('bool', 'typeof(#) == "function"', f)) { 720 if (JS('bool', 'typeof(#) == "function"', f)) {
721 // Behavior when the function is already a JS function is unspecified. 721 // Behavior when the function is already a JS function is unspecified.
722 throw new ArgumentError( 722 throw new ArgumentError(
723 "Function is already a JS function so cannot capture this."); 723 "Function is already a JS function so cannot capture this.");
724 return f; 724 return f;
725 } else { 725 } else {
726 return _convertDartFunctionFastCaptureThis(f); 726 return _convertDartFunctionFastCaptureThis(f);
727 } 727 }
728 } 728 }
729
730 /// Utility methods to efficiently manipulate typed JSInterop objects in cases
731 /// where the name to call is not known at runtime. You should only use these
732 /// methods when the same effect cannot be achieved with @JS annotations.
733 /// These methods would be extension methods on JSObject if Dart supported
734 /// extension methods.
735 class JSNative {
sra1 2016/07/20 18:19:20 Maybe call JSUtils ? JavaScriptUtils ? Or a dart:l
Jacob 2016/07/22 19:28:24 added dart:js_util re-export it as package:js/js
736 /**
737 * WARNING: performance of this method is much worse than other methods
738 * in JSNative. Only use this method as a last resort.
739 *
740 * Recursively converts a JSON-like collection of Dart objects to a
741 * collection of JavaScript objects and returns a [JsObject] proxy to it.
742 *
743 * [object] must be a [Map] or [Iterable], the contents of which are also
744 * converted. Maps and Iterables are copied to a new JavaScript object.
745 * Primitives and other transferrable values are directly converted to their
746 * JavaScript type, and all other objects are proxied.
747 */
748 static jsify(object) {
749 if ((object is! Map) && (object is! Iterable)) {
750 throw new ArgumentError("object must be a Map or Iterable");
751 }
752 return _convertDataTree(object);
753 }
754
755 static _convertDataTree(data) {
756 var _convertedObjects = new HashMap.identity();
757
758 _convert(o) {
759 if (_convertedObjects.containsKey(o)) {
760 return _convertedObjects[o];
761 }
762 if (o is Map) {
763 final convertedMap = JS('=Object', '{}');
764 _convertedObjects[o] = convertedMap;
765 for (var key in o.keys) {
766 JS('=Object', '#[#]=#', convertedMap, key, _convert(o[key]));
767 }
768 return convertedMap;
769 } else if (o is Iterable) {
770 var convertedList = [];
771 _convertedObjects[o] = convertedList;
772 convertedList.addAll(o.map(_convert));
773 return convertedList;
774 } else {
775 return o;
776 }
777 }
778
779 return _convert(data);
780 }
781
782 static JSObject newObject() => JS('=Object', '{}');
783
784 static hasProperty(o, name) => JS('bool', '# in #', name, o);
785 static getProperty(o, name) => JS('Object', '#[#]', o, name);
786 static setProperty(o, name, value) => JS('', '#[#]=#', o, name, value);
787
788 static callMethod(o, String method, List args) =>
789 JS('Object', '#[#].apply(#, #)', o, method, o, args);
790
791 static instanceof(o, Function type) => JS('bool', '# instanceof #', o, type);
sra1 2016/07/20 18:19:20 instanceOf ?
Jacob 2016/07/22 19:28:24 ran it by Bob and he thinks it is reasonable to st
792 static callConstructor(Function constr, List arguments) {
793 if (arguments == null) {
794 return JS('Object', 'new #()', constr);
795 }
796
797 if (JS('bool', '# instanceof Array', arguments)) {
798 int argumentCount = JS('int', '#.length', arguments);
799 switch (argumentCount) {
800 case 0:
801 return JS('Object', 'new #()', constr);
802
803 case 1:
804 var arg0 = JS('', '#[0]', arguments);
805 return JS('Object', 'new #(#)', constr, arg0);
806
807 case 2:
808 var arg0 = JS('', '#[0]', arguments);
809 var arg1 = JS('', '#[1]', arguments);
810 return JS('Object', 'new #(#, #)', constr, arg0, arg1);
811
812 case 3:
813 var arg0 = JS('', '#[0]', arguments);
814 var arg1 = JS('', '#[1]', arguments);
815 var arg2 = JS('', '#[2]', arguments);
816 return JS('Object', 'new #(#, #, #)', constr, arg0, arg1, arg2);
817
818 case 4:
819 var arg0 = JS('', '#[0]', arguments);
820 var arg1 = JS('', '#[1]', arguments);
821 var arg2 = JS('', '#[2]', arguments);
822 var arg3 = JS('', '#[3]', arguments);
823 return JS(
824 'Object', 'new #(#, #, #, #)', constr, arg0, arg1, arg2, arg3);
825 }
826 }
827
828 // The following code solves the problem of invoking a JavaScript
829 // constructor with an unknown number arguments.
830 // First bind the constructor to the argument list using bind.apply().
831 // The first argument to bind() is the binding of 'this', so add 'null' to
832 // the arguments list passed to apply().
833 // After that, use the JavaScript 'new' operator which overrides any binding
834 // of 'this' with the new instance.
835 var args = [null]..addAll(arguments);
836 var factoryFunction = JS('', '#.bind.apply(#, #)', constr, constr, args);
837 // Without this line, calling factoryFunction as a constructor throws
838 JS('String', 'String(#)', factoryFunction);
839 // This could return an UnknownJavaScriptObject, or a native
840 // object for which there is an interceptor
841 return JS('Object', 'new #()', factoryFunction);
842
843 // TODO(sra): Investigate:
844 //
845 // var jsObj = JS('', 'Object.create(#.prototype)', constr);
846 // JS('', '#.apply(#, #)', constr, jsObj,
847 // []..addAll(arguments.map(_convertToJS)));
848 // return _wrapToDart(jsObj);
849 }
850 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698