Chromium Code Reviews| Index: sdk/lib/js/dart2js/js_dart2js.dart |
| diff --git a/sdk/lib/js/dart2js/js_dart2js.dart b/sdk/lib/js/dart2js/js_dart2js.dart |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..f501dfbb8cc6306c964e4d4924ff890b1f2ad574 |
| --- /dev/null |
| +++ b/sdk/lib/js/dart2js/js_dart2js.dart |
| @@ -0,0 +1,206 @@ |
| +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| +// for details. All rights reserved. Use of this source code is governed by a |
| +// BSD-style license that can be found in the LICENSE file. |
| + |
| +library dart.js; |
| + |
| +import 'dart:_foreign_helper' show JS; |
| +import 'dart:_js_helper' show convertDartClosureToJS; |
| + |
| +JsObject get context { |
| + return new JsObject._fromJs(JS('=Object', 'window')); |
| +} |
| + |
| +scoped(f) => f(); |
| + |
| +dynamic retain(Serializable<JsObject> object) {} |
| +void release(Serializable<JsObject> object) {} |
| + |
| +JsObject jsify(dynamic data) => data == null ? null : new JsObject._json(data); |
| + |
| +class Callback implements Serializable<JsFunction> { |
| + final Function _f; // here to allow capture in closure |
| + final bool _withThis; // here to allow capture in closure |
| + dynamic _jsFunction; |
| + |
| + Callback._internal(this._f, this._withThis) { |
| + _jsFunction = JS('=Object', r''' |
| +(function(){ |
| + var f = #; |
| + return function(){ |
| + return f(this, Array.prototype.slice.apply(arguments)); |
| + }; |
| +}).apply(this)''', convertDartClosureToJS(_call, 2)); |
| + } |
| + |
| + _call(thisArg, List args) { |
| + final arguments = new List.from(args); |
| + if (_withThis) arguments.insert(0, thisArg); |
| + final dartArgs = arguments.map(_convertToDart).toList(); |
| + return _convertToJS(Function.apply(_f, dartArgs)); |
| + } |
| + |
| + JsFunction toJs() => new JsFunction._fromJs(_jsFunction); |
| + |
| + dispose() {} |
| + |
| + factory Callback.once(Function f, {bool withThis: false}) => |
| + new Callback._internal(f, withThis); |
| + |
| + factory Callback.many(Function f, {bool withThis: false}) => |
| + new Callback._internal(f, withThis); |
| +} |
| + |
| +class JsObject implements Serializable<JsObject> { |
| + final dynamic _jsObject; |
| + |
| + JsObject._fromJs(this._jsObject); |
| + |
| + factory JsObject(Serializable<JsFunction> constructor, [List arguments]) { |
| + final constr = _convertToJS(constructor); |
| + if (arguments == null) { |
| + return new JsObject._fromJs(JS('=Object', 'new #()', constr)); |
| + } |
| + final args = arguments.map(_convertToJS).toList(); |
| + switch (args.length) { |
| + case 0: |
| + return new JsObject._fromJs(JS('=Object', 'new #()', constr)); |
| + case 1: |
| + return new JsObject._fromJs(JS('=Object', 'new #(#)', constr, args[0])); |
| + case 2: |
| + return new JsObject._fromJs(JS('=Object', 'new #(#,#)', constr, args[0], |
| + args[1])); |
| + case 3: |
| + return new JsObject._fromJs(JS('=Object', 'new #(#,#,#)', constr, |
| + args[0], args[1], args[2])); |
| + case 4: |
| + return new JsObject._fromJs(JS('=Object', 'new #(#,#,#,#)', constr, |
| + args[0], args[1], args[2], args[3])); |
| + case 5: |
| + return new JsObject._fromJs(JS('=Object', 'new #(#,#,#,#,#)', constr, |
| + args[0], args[1], args[2], args[3], args[4])); |
| + case 6: |
| + return new JsObject._fromJs(JS('=Object', 'new #(#,#,#,#,#,#)', constr, |
| + args[0], args[1], args[2], args[3], args[4], args[5])); |
| + case 7: |
| + return new JsObject._fromJs(JS('=Object', 'new #(#,#,#,#,#,#,#)', |
| + constr, args[0], args[1], args[2], args[3], args[4], args[5], |
| + args[6])); |
| + case 8: |
| + return new JsObject._fromJs(JS('=Object', 'new #(#,#,#,#,#,#,#,#)', |
| + constr, args[0], args[1], args[2], args[3], args[4], args[5], |
| + args[6], args[7])); |
| + case 9: |
| + return new JsObject._fromJs(JS('=Object', 'new #(#,#,#,#,#,#,#,#,#)', |
| + constr, args[0], args[1], args[2], args[3], args[4], args[5], |
| + args[6], args[7], args[8])); |
| + case 10: |
| + return new JsObject._fromJs(JS('=Object', 'new #(#,#,#,#,#,#,#,#,#,#)', |
| + constr, args[0], args[1], args[2], args[3], args[4], args[5], |
| + args[6], args[7], args[8], args[9])); |
| + } |
| + return new JsObject._fromJs(JS('=Object', r'''(function(){ |
| +var Type = function(){}; |
| +Type.prototype = #.prototype; |
| +var instance = new Type(); |
| +ret = constructor.apply(instance, #); |
|
vsm
2013/06/11 16:17:44
'constructor' isn't in scope here. I think you ne
alexandre.ardhuin
2013/06/12 21:29:19
Done.
|
| +ret = Object(ret) === ret ? ret : instance; |
| +})()''', constr, args)); |
| + } |
| + |
| + factory JsObject._json(data) => new JsObject._fromJs(_convertDataTree(data)); |
| + |
| + static _convertDataTree(data) { |
| + if (data is Map) { |
| + final convertedData = JS('=Object', '{}'); |
| + for (var key in data.keys) { |
| + JS('=Object', '#[#]=#', convertedData, key, |
| + _convertDataTree(data[key])); |
| + } |
| + return convertedData; |
| + } else if (data is Iterable) { |
| + return data.map(_convertDataTree).toList(); |
| + } else { |
| + return _convertToJS(data); |
| + } |
| + } |
| + |
| + JsObject toJs() => this; |
| + |
| + operator[](key) => _convertToDart(JS('=Object', '#[#]', _convertToJS(this), key)); |
|
vsm
2013/06/11 16:17:44
Nit: line length > 80
alexandre.ardhuin
2013/06/12 21:29:19
Done.
|
| + operator[]=(key, value) => JS('void', '#[#]=#', _convertToJS(this), key, |
| + _convertToJS(value)); |
| + |
| + operator==(other) => identical(this, other) || |
| + (other is JsObject && JS('bool', '# == #', _convertToJS(this), |
| + _convertToJS(other))); |
| + |
| + bool hasProperty(String property) => JS('bool', '# in #', property, |
| + _convertToJS(this)); |
| + |
| + void deleteProperty(String name) { |
| + JS('void', 'delete #[#]', _convertToJS(this), name); |
| + } |
| + |
| + bool instanceof(Serializable<JsFunction> type) => |
| + JS('bool', '# instanceof #', _convertToJS(this), _convertToJS(type)); |
| + |
| + String toString() { |
| + try { |
| + return JS('String', '#.toString()', _convertToJS(this)); |
| + } catch(e) { |
| + return super.toString(); |
| + } |
| + } |
| + |
| + callMethod(String name, [List args]) => |
| + _convertToDart(JS('=Object', '#[#].apply(#, #)', _convertToJS(this), name, |
| + _convertToJS(this), |
| + args == null ? null : args.map(_convertToJS).toList())); |
| +} |
| + |
| +class JsFunction extends JsObject implements Serializable<JsFunction> { |
| + JsFunction._fromJs(jsObject) : super._fromJs(jsObject); |
| + apply(thisArg, [List args]) => |
| + _convertToDart(JS('=Object', '#.apply(#, #)', _convertToJS(this), |
| + _convertToJS(thisArg), |
| + args == null ? null : args.map(_convertToJS).toList())); |
| +} |
| + |
| +abstract class Serializable<T> { |
| + T toJs(); |
| +} |
| + |
| +class _DartProxy { |
| + dynamic o; |
| + _DartProxy(this.o); |
| +} |
| + |
| +dynamic _convertToJS(dynamic o) { |
| + if (o == null) { |
| + return null; |
| + } else if (o is String || o is num || o is bool) { |
| + return o; |
| + } else if (o is JsObject) { |
| + return o._jsObject; |
| + } else if (o is Serializable) { |
| + return _convertToJS(o.toJs()); |
| + } else { |
| + return new _DartProxy(o); |
| + } |
| +} |
|
vsm
2013/06/11 16:17:44
Nit: space between functions.
alexandre.ardhuin
2013/06/12 21:29:19
Done.
|
| +dynamic _convertToDart(dynamic o) { |
| + if (o == null) { |
| + return null; |
| + } else if (o is num || o is String || o is bool) { |
| + return o; |
| + } else if (JS('bool', '# instanceof Function', o)) { |
| + return new JsFunction._fromJs(JS('Function', '#', o)); |
|
vsm
2013/06/11 16:17:44
I think this should be JS('=Object', ...) as well.
alexandre.ardhuin
2013/06/12 21:29:19
Done.
|
| + } else if (o is _DartProxy) { |
| + return o.o; |
| + } else { |
| + return new JsObject._fromJs(JS('=Object', '#', o)); |
| + } |
| +} |
| + |
| +int proxyCount({all: false, dartOnly: false, jsOnly: false}) => 0; |