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

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

Issue 27514003: A few API changes: (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 2 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | tests/html/js_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 library dart.js; 5 library dart.js;
6 6
7 import 'dart:collection' show HashMap;
7 import 'dart:_foreign_helper' show JS, DART_CLOSURE_TO_JS; 8 import 'dart:_foreign_helper' show JS, DART_CLOSURE_TO_JS;
9 import 'dart:_interceptors' show JavaScriptObject, UnknownJavaScriptObject;
8 import 'dart:_js_helper' show Primitives, convertDartClosureToJS; 10 import 'dart:_js_helper' show Primitives, convertDartClosureToJS;
9 11
10 final JsObject context = new JsObject._fromJs(Primitives.computeGlobalThis()); 12 final JsObject context = new JsObject._fromJs(Primitives.computeGlobalThis());
11 13
12 JsObject jsify(dynamic data) => data == null ? null : new JsObject._json(data);
13
14 class Callback implements Serializable<JsFunction> {
15 final Function _f; // here to allow capture in closure
16 final bool _withThis; // here to allow capture in closure
17 dynamic _jsFunction;
18
19 Callback._(this._f, this._withThis) {
20 _jsFunction = JS('', r'''
21 (function(){
22 var f = #;
23 return function(){
24 return f(this, Array.prototype.slice.apply(arguments));
25 };
26 }).apply(this)''', convertDartClosureToJS(_call, 2));
27 }
28
29 factory Callback(Function f) => new Callback._(f, false);
30 factory Callback.withThis(Function f) => new Callback._(f, true);
31
32 _call(thisArg, List args) {
33 final arguments = new List.from(args);
34 if (_withThis) arguments.insert(0, thisArg);
35 final dartArgs = arguments.map(_convertToDart).toList();
36 return _convertToJS(Function.apply(_f, dartArgs));
37 }
38
39 JsFunction toJs() => new JsFunction._fromJs(_jsFunction);
40 }
41
42 /*
43 * TODO(justinfagnani): add tests and make public when we remove Callback.
44 *
45 * Returns a [JsFunction] that captures its 'this' binding and calls [f]
46 * with the value of this passed as the first argument.
47 */
48 JsFunction _captureThis(Function f) =>
49 new JsFunction._fromJs(_convertDartFunction(f, captureThis: true));
50
51 _convertDartFunction(Function f, {bool captureThis: false}) { 14 _convertDartFunction(Function f, {bool captureThis: false}) {
52 return JS('', 15 return JS('',
53 'function(_call, f, captureThis) {' 16 'function(_call, f, captureThis) {'
54 'return function() {' 17 'return function() {'
55 'return _call(f, captureThis, this, ' 18 'return _call(f, captureThis, this, '
56 'Array.prototype.slice.apply(arguments));' 19 'Array.prototype.slice.apply(arguments));'
57 '}' 20 '}'
58 '}(#, #, #)', DART_CLOSURE_TO_JS(_callDartFunction), f, captureThis); 21 '}(#, #, #)', DART_CLOSURE_TO_JS(_callDartFunction), f, captureThis);
59 } 22 }
60 23
61 _callDartFunction(callback, bool captureThis, self, List arguments) { 24 _callDartFunction(callback, bool captureThis, self, List arguments) {
62 if (captureThis) { 25 if (captureThis) {
63 arguments = [self]..addAll(arguments); 26 arguments = [self]..addAll(arguments);
64 } 27 }
65 var dartArgs = arguments.map(_convertToDart).toList(); 28 var dartArgs = arguments.map(_convertToDart).toList();
66 return _convertToJS(Function.apply(callback, dartArgs)); 29 return _convertToJS(Function.apply(callback, dartArgs));
67 } 30 }
68 31
69 32
70 class JsObject implements Serializable<JsObject> { 33 class JsObject implements Serializable<JsObject> {
71 // The wrapped JS object. 34 // The wrapped JS object.
72 final dynamic _jsObject; 35 final dynamic _jsObject;
73 36
74 JsObject._fromJs(this._jsObject) { 37 JsObject._fromJs(this._jsObject) {
38 assert(_jsObject != null);
75 // Remember this proxy for the JS object 39 // Remember this proxy for the JS object
76 _getDartProxy(_jsObject, _DART_OBJECT_PROPERTY_NAME, (o) => this); 40 _getDartProxy(_jsObject, _DART_OBJECT_PROPERTY_NAME, (o) => this);
77 } 41 }
78 42
43 /**
44 * Expert users only:
45 * Use this constructor only if you wish to get access to JS expandos
46 * attached to a WebKit native object such as a Node.
47 * An exception will be thrown if a primitive type is passed in passing one
48 * of these types to this method indicates an error.
49 */
50 factory JsObject.fromDartObject(Object object) {
alexandre.ardhuin 2013/10/16 19:32:11 Rename to `fromBrowserObject`.
justinfagnani 2013/10/18 03:19:08 Done.
51 if (object is num || object is String || object is bool || object == null) {
52 throw new IllegalArgumentException(
53 "object cannot be a num, string, bool, or null");
54 }
55 return new JsObject._fromJs(_convertToJS(object));
56 }
57
58 /**
59 * Converts a json-like [data] to a JavaScript map or array and return a
60 * [JsObject] to it.
61 */
62 factory JsObject.jsify(Object object) {
63 if ((object is! Map) && (object is! Iterable)) {
64 throw new IllegalArgumentException("object must be a Map or Iterable");
65 }
66 return new JsObject._fromJs(_convertDataTree(object));
67 }
68
79 // TODO(vsm): Type constructor as Serializable<JsFunction> when 69 // TODO(vsm): Type constructor as Serializable<JsFunction> when
80 // dartbug.com/11854 is fixed. 70 // dartbug.com/11854 is fixed.
81 factory JsObject(constructor, [List arguments]) { 71 factory JsObject(constructor, [List arguments]) {
82 var constr = _convertToJS(constructor); 72 var constr = _convertToJS(constructor);
83 if (arguments == null) { 73 if (arguments == null) {
84 return new JsObject._fromJs(JS('', 'new #()', constr)); 74 return new JsObject._fromJs(JS('', 'new #()', constr));
85 } 75 }
86 // The following code solves the problem of invoking a JavaScript 76 // The following code solves the problem of invoking a JavaScript
87 // constructor with an unknown number arguments. 77 // constructor with an unknown number arguments.
88 // First bind the constructor to the argument list using bind.apply(). 78 // First bind the constructor to the argument list using bind.apply().
89 // The first argument to bind() is the binding of 'this', so add 'null' to 79 // The first argument to bind() is the binding of 'this', so add 'null' to
90 // the arguments list passed to apply(). 80 // the arguments list passed to apply().
91 // After that, use the JavaScript 'new' operator which overrides any binding 81 // After that, use the JavaScript 'new' operator which overrides any binding
92 // of 'this' with the new instance. 82 // of 'this' with the new instance.
93 var args = [null]..addAll(arguments.map(_convertToJS)); 83 var args = [null]..addAll(arguments.map(_convertToJS));
94 var factoryFunction = JS('', '#.bind.apply(#, #)', constr, constr, args); 84 var factoryFunction = JS('', '#.bind.apply(#, #)', constr, constr, args);
95 // Without this line, calling factoryFunction as a constructor throws 85 // Without this line, calling factoryFunction as a constructor throws
96 JS('String', 'String(#)', factoryFunction); 86 JS('String', 'String(#)', factoryFunction);
97 return new JsObject._fromJs(JS('', 'new #()', factoryFunction)); 87 // This could return an UnknownJavaScriptObject, or a native
88 // object for which there is an interceptor
89 var jsObj = JS('JavaScriptObject', 'new #()', factoryFunction);
90 // print("UnknownJavaScriptObject: ${jsObj is UnknownJavaScriptObject}");
alexandre.ardhuin 2013/10/16 19:32:11 Remove these comments ?
justinfagnani 2013/10/18 03:19:08 Done.
91 // print("JavaScriptObject: ${jsObj is JavaScriptObject}");
92 // JS('void', 'console.log("jsObj: " + #)', jsObj);
93 return new JsObject._fromJs(jsObj);
98 } 94 }
99 95
100 factory JsObject._json(data) => new JsObject._fromJs(_convertDataTree(data)); 96 // TODO: handle cycles
97 static _convertDataTree(data) {
98 var _convertedObjects = new HashMap.identity();
101 99
102 static _convertDataTree(data) { 100 _convert(o) {
103 if (data is Map) { 101 if (_convertedObjects.containsKey(o)) {
104 final convertedData = JS('=Object', '{}'); 102 return _convertedObjects[o];
105 for (var key in data.keys) {
106 JS('=Object', '#[#]=#', convertedData, key,
107 _convertDataTree(data[key]));
108 } 103 }
109 return convertedData; 104 if (o is Map) {
110 } else if (data is Iterable) { 105 final convertedMap = JS('=Object', '{}');
111 return data.map(_convertDataTree).toList(); 106 _convertedObjects[o] = convertedMap;
112 } else { 107 for (var key in o.keys) {
113 return _convertToJS(data); 108 JS('=Object', '#[#]=#', convertedMap, key, _convert(o[key]));
109 }
110 return convertedMap;
111 } else if (o is Iterable) {
112 var convertedList = [];
113 _convertedObjects[o] = convertedList;
114 convertedList.addAll(o.map(_convert));
115 return convertedList;
116 } else {
117 return _convertToJS(o);
118 }
114 } 119 }
120
121 return _convert(data);
115 } 122 }
116 123
117 JsObject toJs() => this; 124 JsObject toJs() => this;
118 125
119 /** 126 /**
120 * Returns the value associated with [key] from the proxied JavaScript 127 * Returns the value associated with [key] from the proxied JavaScript
121 * object. 128 * object.
122 * 129 *
123 * [key] must either be a [String] or [int]. 130 * [key] must either be a [String] or [int].
124 */ 131 */
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 throw new ArgumentError("name is not a String or int"); 188 throw new ArgumentError("name is not a String or int");
182 } 189 }
183 return _convertToDart(JS('', '#[#].apply(#, #)', _jsObject, name, 190 return _convertToDart(JS('', '#[#].apply(#, #)', _jsObject, name,
184 _jsObject, 191 _jsObject,
185 args == null ? null : args.map(_convertToJS).toList())); 192 args == null ? null : args.map(_convertToJS).toList()));
186 } 193 }
187 } 194 }
188 195
189 class JsFunction extends JsObject implements Serializable<JsFunction> { 196 class JsFunction extends JsObject implements Serializable<JsFunction> {
190 197
198 /*
199 * Returns a [JsFunction] that captures its 'this' binding and calls [f]
200 * with the value of this passed as the first argument.
201 */
202 factory JsFunction.withThis(Function f) {
203 var jsFunc = _convertDartFunction(f, captureThis: true);
204 return new JsFunction._fromJs(jsFunc);
205 }
206
191 JsFunction._fromJs(jsObject) : super._fromJs(jsObject); 207 JsFunction._fromJs(jsObject) : super._fromJs(jsObject);
192 208
193 dynamic apply(thisArg, [List args]) => 209 dynamic apply(thisArg, [List args]) =>
194 _convertToDart(JS('', '#.apply(#, #)', _jsObject, 210 _convertToDart(JS('', '#.apply(#, #)', _jsObject,
195 _convertToJS(thisArg), 211 _convertToJS(thisArg),
196 args == null ? null : args.map(_convertToJS).toList())); 212 args == null ? null : args.map(_convertToJS).toList()));
197 } 213 }
198 214
199 abstract class Serializable<T> { 215 abstract class Serializable<T> {
200 T toJs(); 216 T toJs();
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
272 } 288 }
273 289
274 Object _getDartProxy(o, String propertyName, createProxy(o)) { 290 Object _getDartProxy(o, String propertyName, createProxy(o)) {
275 var dartProxy = JS('', '#[#]', o, propertyName); 291 var dartProxy = JS('', '#[#]', o, propertyName);
276 if (dartProxy == null) { 292 if (dartProxy == null) {
277 dartProxy = createProxy(o); 293 dartProxy = createProxy(o);
278 _defineProperty(o, propertyName, dartProxy); 294 _defineProperty(o, propertyName, dartProxy);
279 } 295 }
280 return dartProxy; 296 return dartProxy;
281 } 297 }
OLDNEW
« no previous file with comments | « no previous file | tests/html/js_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698