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 |
index 268263bf92893c80b3f34a4ec4e8b9f8d2eab87d..21c3b1811d00fe9789daf69fb4f9e68a441af847 100644 |
--- a/sdk/lib/js/dart2js/js_dart2js.dart |
+++ b/sdk/lib/js/dart2js/js_dart2js.dart |
@@ -17,7 +17,7 @@ class Callback implements Serializable<JsFunction> { |
dynamic _jsFunction; |
Callback._(this._f, this._withThis) { |
- _jsFunction = JS('=Object', r''' |
+ _jsFunction = JS('', r''' |
(function(){ |
var f = #; |
return function(){ |
@@ -68,6 +68,7 @@ _callDartFunction(callback, bool captureThis, self, List arguments) { |
class JsObject implements Serializable<JsObject> { |
+ // the wrapped JS object |
ahe
2013/10/11 12:40:51
Please convert to proper sentence, that is, start
justinfagnani
2013/10/12 21:16:22
Done.
|
final dynamic _jsObject; |
JsObject._fromJs(this._jsObject) { |
@@ -77,57 +78,22 @@ class JsObject implements Serializable<JsObject> { |
// TODO(vsm): Type constructor as Serializable<JsFunction> when |
// dartbug.com/11854 is fixed. |
- factory JsObject(var constructor, [List arguments]) { |
- final constr = _convertToJS(constructor); |
+ factory JsObject(constructor, [List arguments]) { |
+ var constr = _convertToJS(constructor); |
if (arguments == null) { |
- return new JsObject._fromJs(JS('=Object', 'new #()', constr)); |
+ return new JsObject._fromJs(JS('', '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)); |
+ // The following code solves the problem of invoking a JavaScript |
+ // constructor with an unknown number arguments. |
+ // First bind the constructor to the argument list using bind.apply(). |
+ // The first argument to bind() is the binding of 'this', so add 'null' to |
+ // the arguments list passed to apply(). |
+ // After that, use the JavaScript 'new' operator which overrides any binding |
+ // of 'this' with the new instance. |
+ var args = [null]..addAll(arguments.map(_convertToJS)); |
+ var factoryFunction = JS('', '#.bind.apply(#, #)', constr, constr, args); |
+ JS('void', 'console.log(#)', factoryFunction); |
alexandre.ardhuin
2013/10/11 14:07:13
log to remove ?
justinfagnani
2013/10/12 21:16:22
There's a very strange heisenbug here. Without the
|
+ return new JsObject._fromJs(JS('', 'new #()', factoryFunction)); |
} |
factory JsObject._json(data) => new JsObject._fromJs(_convertDataTree(data)); |
@@ -149,47 +115,83 @@ return ret; |
JsObject toJs() => this; |
- operator[](key) => |
- _convertToDart(JS('=Object', '#[#]', _convertToJS(this), key)); |
- |
- operator[]=(key, value) => JS('void', '#[#]=#', _convertToJS(this), key, |
- _convertToJS(value)); |
+ /** |
+ * Returns the value associated with [key] from the proxied JavaScript |
+ * object. |
+ * |
+ * [key] must either be a [String] or [int]. |
+ */ |
+ // TODO(justinfagnani): rename key/name to property |
+ dynamic operator[](dynamic key) { |
ahe
2013/10/11 12:40:51
Remove dynamic (twice).
justinfagnani
2013/10/12 21:16:22
Done.
|
+ if (key is! String && key is! int) { |
+ throw new ArgumentError("key is not a String or int"); |
+ } |
+ return _convertToDart(JS('', '#[#]', _jsObject, key)); |
+ } |
+ |
+ /** |
+ * Sets the value associated with [key] from the proxied JavaScript |
+ * object. |
+ * |
+ * [key] must either be a [String] or [int]. |
+ */ |
+ operator[]=(String key, value) { |
alexandre.ardhuin
2013/10/11 14:07:13
Change "key" type to dynamic to be consistant with
justinfagnani
2013/10/12 21:16:22
Done.
|
+ if (key is! String && key is! int) { |
+ throw new ArgumentError("key is not a String or int"); |
+ } |
+ JS('', '#[#]=#', _jsObject, key, _convertToJS(value)); |
+ } |
int get hashCode => 0; |
operator==(other) => other is JsObject && |
- JS('bool', '# === #', _convertToJS(this), _convertToJS(other)); |
+ JS('bool', '# === #', _jsObject, other._jsObject); |
- bool hasProperty(String property) => JS('bool', '# in #', property, |
- _convertToJS(this)); |
+ bool hasProperty(String name) { |
alexandre.ardhuin
2013/10/11 14:07:13
Change "name" type to dynamic.
justinfagnani
2013/10/12 21:16:22
Done.
|
+ if (name is! String && name is! int) { |
+ throw new ArgumentError("name is not a String or int"); |
+ } |
+ return JS('bool', '# in #', name, _jsObject); |
+ } |
void deleteProperty(String name) { |
alexandre.ardhuin
2013/10/11 14:07:13
Change "name" type to dynamic.
justinfagnani
2013/10/12 21:16:22
Done.
|
- JS('void', 'delete #[#]', _convertToJS(this), name); |
+ if (name is! String && name is! int) { |
+ throw new ArgumentError("name is not a String or int"); |
+ } |
+ JS('bool', 'delete #[#]', _jsObject, name); |
} |
// TODO(vsm): Type type as Serializable<JsFunction> when |
// dartbug.com/11854 is fixed. |
- bool instanceof(var type) => |
- JS('bool', '# instanceof #', _convertToJS(this), _convertToJS(type)); |
+ bool instanceof(JsFunction type) { |
alexandre.ardhuin
2013/10/11 14:07:13
Remove JsFunction otherwise Serializable<JsFunctio
justinfagnani
2013/10/12 21:16:22
Done.
|
+ if (type is! JsFunction) throw new ArgumentError("type is not a JsFunction"); |
ahe
2013/10/11 12:40:51
Long line.
justinfagnani
2013/10/12 21:16:22
Done.
|
+ return JS('bool', '# instanceof #', _jsObject, type._jsObject); |
+ } |
String toString() { |
try { |
- return JS('String', '#.toString()', _convertToJS(this)); |
+ return JS('String', 'String(#)', _jsObject); |
} 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())); |
+ callMethod(String name, [List args]) { |
+ if (name is! String && name is! int) { |
+ throw new ArgumentError("name is not a String or int"); |
+ } |
+ return _convertToDart(JS('', '#[#].apply(#, #)', _jsObject, name, |
+ _jsObject, |
+ 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), |
+ _convertToDart(JS('', '#.apply(#, #)', _jsObject, |
_convertToJS(thisArg), |
args == null ? null : args.map(_convertToJS).toList())); |
} |
@@ -243,17 +245,16 @@ dynamic _getJsProxy(o, String propertyName, createProxy(o)) { |
// converts a Dart object to a reference to a native JS object |
// which might be a DartObject JS->Dart proxy |
dynamic _convertToDart(dynamic o) { |
ahe
2013/10/11 12:40:51
Remove dynamic (twice).
justinfagnani
2013/10/12 21:16:22
Done, but changed the return type to Object to ind
|
- 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)) { |
+ if (JS('bool', '# == null', o) || |
+ JS('bool', 'typeof # == "string"', o) || |
+ JS('bool', 'typeof # == "number"', o) || |
+ JS('bool', 'typeof # == "boolean"', o)) { |
return o; |
- } else if (JS('bool', '# instanceof Function', o)) { |
+ } else if (JS('bool', 'typeof # == "function"', o)) { |
return _getDartProxy(o, _DART_CLOSURE_PROPERTY_NAME, |
(o) => new JsFunction._fromJs(o)); |
- } else if (JS('bool', '# instanceof DartObject', o)) { |
- return JS('var', '#.o', o); |
+ } else if (JS('bool', '#.constructor === DartObject', o)) { |
+ return JS('', '#.o', o); |
} else { |
return _getDartProxy(o, _DART_OBJECT_PROPERTY_NAME, |
(o) => new JsObject._fromJs(o)); |