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..282e5fab99098b7cb81972ec4e952dc82d8d1362 |
--- /dev/null |
+++ b/sdk/lib/js/dart2js/js_dart2js.dart |
@@ -0,0 +1,197 @@ |
+// 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')); |
+} |
+ |
+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._(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)); |
+ } |
+ |
+ factory Callback(Function f) => new Callback._(f, false); |
+ factory Callback.withThis(Function f) => new Callback._(f, true); |
+ |
+ _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); |
+} |
+ |
+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 = #.apply(instance, #); |
+ret = Object(ret) === ret ? ret : instance; |
+return ret; |
+})()''', constr, 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)); |
+ operator[]=(key, value) => JS('void', '#[#]=#', _convertToJS(this), key, |
+ _convertToJS(value)); |
+ |
+ int get hashCode => 0; |
+ |
+ operator==(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(); |
+} |
+ |
+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 if (o is Function) { |
+ return _convertToJS(new Callback(o)); |
+ } else { |
+ return JS('=Object', 'new DartProxy(#)', o); |
+ } |
+} |
+ |
+dynamic _convertToDart(dynamic o) { |
+ if (JS('bool', '# == null', o)) { |
+ return null; |
+ } else if (JS('bool', 'typeof # == "string" || # instanceof String', o, o) || |
+ JS('bool', 'typeof # == "number" || # instanceof Number', o, o) || |
+ JS('bool', 'typeof # == "boolean" || # instanceof Boolean', o, o)) { |
+ return o; |
+ } else if (JS('bool', '# instanceof Function', o)) { |
+ return new JsFunction._fromJs(JS('=Object', '#', o)); |
+ } else if (JS('bool', '# instanceof DartProxy', o)) { |
+ return JS('var', '#.o', o); |
+ } else { |
+ return new JsObject._fromJs(JS('=Object', '#', o)); |
+ } |
+} |