Chromium Code Reviews| 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); |
| } |