Index: pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/operations.dart |
diff --git a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/operations.dart b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/operations.dart |
index d936333eb597ac7899138f4fad420911976adc1e..d7f787a597dbf80b5270e45bab5b23bab8e77c70 100644 |
--- a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/operations.dart |
+++ b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/operations.dart |
@@ -14,7 +14,7 @@ class InvocationImpl extends Invocation { |
final bool isGetter; |
final bool isSetter; |
- InvocationImpl(String memberName, this.positionalArguments, |
+ InvocationImpl(memberName, this.positionalArguments, |
{namedArguments, |
this.isMethod: false, |
this.isGetter: false, |
@@ -29,12 +29,18 @@ class InvocationImpl extends Invocation { |
} |
} |
+// Warning: dload, dput, and dsend assume they are never called on methods |
+// implemented by the Object base class as those methods can always be |
+// statically resolved. |
dload(obj, field) { |
var f = _canonicalMember(obj, field); |
+ |
_trackCall(obj); |
if (f != null) { |
- if (hasMethod(obj, f)) return bind(obj, f, JS('', 'void 0')); |
- return JS('', '#[#]', obj, f); |
+ var type = getType(obj); |
+ |
+ if (hasField(type, f) || hasGetter(type, f)) return JS('', '#[#]', obj, f); |
+ if (hasMethod(type, f)) return bind(obj, f, JS('', 'void 0')); |
} |
return noSuchMethod( |
obj, new InvocationImpl(field, JS('', '[]'), isGetter: true)); |
@@ -44,7 +50,25 @@ dput(obj, field, value) { |
var f = _canonicalMember(obj, field); |
_trackCall(obj); |
if (f != null) { |
- return JS('', '#[#] = #', obj, f, value); |
+ var type = getType(obj); |
+ var setter = getSetterType(type, f); |
Jennifer Messerly
2017/01/24 03:51:03
Possibly calling this setterType would be a bit mo
Jacob
2017/01/24 19:12:32
agreed. cleaned up.
|
+ if (JS('bool', '# != void 0', setter)) { |
+ // TODO(jacobr): throw a type error instead of a NoSuchMethodError if |
+ // the type of the setter doesn't match. |
+ if (instanceOfOrNull(value, JS('', '#.args[0]', setter))) { |
+ return JS('', '#[#] = #', obj, f, value); |
+ } |
+ } else { |
+ var field = getFieldType(type, f); |
+ // TODO(jacobr): propagate metadata tracking which fields are private. |
Jennifer Messerly
2017/01/24 03:51:03
What does this mean? It shouldn't be possible to g
Jacob
2017/01/24 19:12:32
Done.
It means I got distracted writing the commen
|
+ if (JS('bool', '# != void 0', field)) { |
+ // TODO(jacobr): throw a type error instead of a NoSuchMethodError if |
+ // the type of the field doesn't match. |
+ if (instanceOfOrNull(value, field)) { |
+ return JS('', '#[#] = #', obj, f, value); |
+ } |
+ } |
+ } |
} |
return noSuchMethod( |
obj, new InvocationImpl(field, JS('', '[#]', value), isSetter: true)); |
@@ -89,8 +113,42 @@ _checkApply(type, actuals) => JS( |
return true; |
})()'''); |
-Symbol _dartSymbol(name) => |
- JS('', '#(#.new(#.toString()))', const_, Symbol, name); |
+_toSymbolName(symbol) => JS( |
+ '', |
+ '''(() => { |
+ let str = $symbol.toString(); |
+ // Strip leading 'Symbol(' and trailing ')' |
+ return str.substring(7, str.length-1); |
+ })()'''); |
+ |
+_toDisplayName(name) => JS( |
+ '', |
+ '''(() => { |
+ // Names starting with _ are escaped names used to disambiguate Dart and |
+ // JS names. |
+ if ($name[0] === '_') { |
+ // Inverse of |
+ switch($name) { |
+ case '_get': |
+ return '[]'; |
+ case '_set': |
+ return '[]='; |
+ case '_negate': |
+ return 'unary-'; |
+ case '_constructor': |
+ case '_prototype': |
+ return $name.substring(1); |
+ } |
+ } |
+ return $name; |
+ })()'''); |
+ |
+Symbol _dartSymbol(name) { |
+ return (JS('bool', 'typeof # === "symbol"', name)) |
+ ? JS('', '#(new #.es6(#, #))', const_, _internal.Symbol, |
+ _toSymbolName(name), name) |
+ : JS('', '#(#.new(#))', const_, Symbol, _toDisplayName(name)); |
+} |
/// Extracts the named argument array from a list of arguments, and returns it. |
// TODO(jmesserly): we need to handle named arguments better. |
@@ -121,7 +179,7 @@ _checkAndCall(f, ftype, obj, typeArgs, args, name) => JS( |
// We're not a function (and hence not a method either) |
// Grab the `call` method if it's not a function. |
if ($f != null) { |
- $ftype = $getMethodType($f, 'call'); |
+ $ftype = $getMethodType($getType($f), 'call'); |
$f = $f.call; |
} |
if (!($f instanceof Function)) { |
@@ -303,7 +361,9 @@ _callMethod(obj, name, typeArgs, args, displayName) { |
obj, new InvocationImpl(displayName, args, isMethod: true)); |
} |
var f = obj != null ? JS('', '#[#]', obj, symbol) : null; |
- var ftype = getMethodType(obj, symbol); |
+ var type = getType(obj); |
+ var ftype = getMethodType(type, symbol); |
+ // No such method if dart object and ftype is missing. |
return _checkAndCall(f, ftype, obj, typeArgs, args, displayName); |
} |