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

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: 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 | « pkg/js/pubspec.yaml ('k') | tests/html/js_native_test.dart » ('j') | 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 708 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 {
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) => JS('Object', '#[#].apply(#, #)', o, method, o, args);
Alan Knight 2016/07/19 16:56:04 nit: line length
Jacob 2016/07/19 17:42:19 Done. Ran dartfmt.
789
790 static instanceof(o, Function type) => JS('bool', '# instanceof #', o, type);
791 static callConstructor(Function constr, List arguments) {
792 if (arguments == null) {
793 return JS('Object', 'new #()', constr);
794 }
795
796 if (JS('bool', '# instanceof Array', arguments)) {
797 int argumentCount = JS('int', '#.length', arguments);
798 switch (argumentCount) {
799 case 0:
800 return JS('Object', 'new #()', constr);
801
802 case 1:
803 var arg0 = JS('', '#[0]', arguments);
804 return JS('Object', 'new #(#)', constr, arg0);
805
806 case 2:
807 var arg0 = JS('', '#[0]', arguments);
808 var arg1 = JS('', '#[1]', arguments);
809 return JS('Object', 'new #(#, #)', constr, arg0, arg1);
810
811 case 3:
812 var arg0 = JS('', '#[0]', arguments);
813 var arg1 = JS('', '#[1]', arguments);
814 var arg2 = JS('', '#[2]', arguments);
815 return JS('Object', 'new #(#, #, #)', constr, arg0, arg1, arg2);
816
817 case 4:
818 var arg0 = JS('', '#[0]', arguments);
819 var arg1 = JS('', '#[1]', arguments);
820 var arg2 = JS('', '#[2]', arguments);
821 var arg3 = JS('', '#[3]', arguments);
822 return JS('Object', 'new #(#, #, #, #)', constr, arg0, arg1, arg2, arg 3);
Alan Knight 2016/07/19 16:56:04 Also line length
Jacob 2016/07/19 17:42:19 Done.
823 }
824 }
825
826 // The following code solves the problem of invoking a JavaScript
827 // constructor with an unknown number arguments.
828 // First bind the constructor to the argument list using bind.apply().
829 // The first argument to bind() is the binding of 'this', so add 'null' to
830 // the arguments list passed to apply().
831 // After that, use the JavaScript 'new' operator which overrides any binding
832 // of 'this' with the new instance.
833 var args = [null]..addAll(arguments);
834 var factoryFunction = JS('', '#.bind.apply(#, #)', constr, constr, args);
835 // Without this line, calling factoryFunction as a constructor throws
836 JS('String', 'String(#)', factoryFunction);
837 // This could return an UnknownJavaScriptObject, or a native
838 // object for which there is an interceptor
839 return JS('Object', 'new #()', factoryFunction);
840
841 // TODO(sra): Investigate:
842 //
843 // var jsObj = JS('', 'Object.create(#.prototype)', constr);
844 // JS('', '#.apply(#, #)', constr, jsObj,
845 // []..addAll(arguments.map(_convertToJS)));
846 // return _wrapToDart(jsObj);
847 }
848 }
OLDNEW
« no previous file with comments | « pkg/js/pubspec.yaml ('k') | tests/html/js_native_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698