Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(7)

Side by Side Diff: pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/operations.dart

Issue 2623053004: Fix noSuchMethod handling of methods that are also extension methods. Fix noSuchMethod handling of … (Closed)
Patch Set: Fix noSuchMethod handling of methods that are also extension methods. Fix noSuchMethod handling of … Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 /// This library defines runtime operations on objects used by the code 5 /// This library defines runtime operations on objects used by the code
6 /// generator. 6 /// generator.
7 part of dart._runtime; 7 part of dart._runtime;
8 8
9 class InvocationImpl extends Invocation { 9 class InvocationImpl extends Invocation {
10 final Symbol memberName; 10 final Symbol memberName;
11 final List positionalArguments; 11 final List positionalArguments;
12 final Map<Symbol, dynamic> namedArguments; 12 final Map<Symbol, dynamic> namedArguments;
13 final bool isMethod; 13 final bool isMethod;
14 final bool isGetter; 14 final bool isGetter;
15 final bool isSetter; 15 final bool isSetter;
16 16
17 InvocationImpl(String memberName, this.positionalArguments, 17 InvocationImpl(memberName, this.positionalArguments,
18 {namedArguments, 18 {namedArguments,
19 this.isMethod: false, 19 this.isMethod: false,
20 this.isGetter: false, 20 this.isGetter: false,
21 this.isSetter: false}) 21 this.isSetter: false})
22 : memberName = _dartSymbol(memberName), 22 : memberName = _dartSymbol(memberName),
23 namedArguments = _namedArgsToSymbols(namedArguments); 23 namedArguments = _namedArgsToSymbols(namedArguments);
24 24
25 static Map<Symbol, dynamic> _namedArgsToSymbols(namedArgs) { 25 static Map<Symbol, dynamic> _namedArgsToSymbols(namedArgs) {
26 if (namedArgs == null) return {}; 26 if (namedArgs == null) return {};
27 return new Map.fromIterable(getOwnPropertyNames(namedArgs), 27 return new Map.fromIterable(getOwnPropertyNames(namedArgs),
28 key: _dartSymbol, value: (k) => JS('', '#[#]', namedArgs, k)); 28 key: _dartSymbol, value: (k) => JS('', '#[#]', namedArgs, k));
29 } 29 }
30 } 30 }
31 31
32 // Warning: dload, dput, and dsend assume they are never called on methods
33 // implemented by the Object base class as those methods can always be
34 // statically resolved.
32 dload(obj, field) { 35 dload(obj, field) {
33 var f = _canonicalMember(obj, field); 36 var f = _canonicalMember(obj, field);
37
34 _trackCall(obj); 38 _trackCall(obj);
35 if (f != null) { 39 if (f != null) {
36 if (hasMethod(obj, f)) return bind(obj, f, JS('', 'void 0')); 40 var type = getType(obj);
37 return JS('', '#[#]', obj, f); 41
42 if (hasField(type, f) || hasGetter(type, f)) return JS('', '#[#]', obj, f);
43 if (hasMethod(type, f)) return bind(obj, f, JS('', 'void 0'));
38 } 44 }
39 return noSuchMethod( 45 return noSuchMethod(
40 obj, new InvocationImpl(field, JS('', '[]'), isGetter: true)); 46 obj, new InvocationImpl(field, JS('', '[]'), isGetter: true));
41 } 47 }
42 48
43 dput(obj, field, value) { 49 dput(obj, field, value) {
44 var f = _canonicalMember(obj, field); 50 var f = _canonicalMember(obj, field);
45 _trackCall(obj); 51 _trackCall(obj);
46 if (f != null) { 52 if (f != null) {
47 return JS('', '#[#] = #', obj, f, value); 53 var type = getType(obj);
54 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.
55 if (JS('bool', '# != void 0', setter)) {
56 // TODO(jacobr): throw a type error instead of a NoSuchMethodError if
57 // the type of the setter doesn't match.
58 if (instanceOfOrNull(value, JS('', '#.args[0]', setter))) {
59 return JS('', '#[#] = #', obj, f, value);
60 }
61 } else {
62 var field = getFieldType(type, f);
63 // 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
64 if (JS('bool', '# != void 0', field)) {
65 // TODO(jacobr): throw a type error instead of a NoSuchMethodError if
66 // the type of the field doesn't match.
67 if (instanceOfOrNull(value, field)) {
68 return JS('', '#[#] = #', obj, f, value);
69 }
70 }
71 }
48 } 72 }
49 return noSuchMethod( 73 return noSuchMethod(
50 obj, new InvocationImpl(field, JS('', '[#]', value), isSetter: true)); 74 obj, new InvocationImpl(field, JS('', '[#]', value), isSetter: true));
51 } 75 }
52 76
53 /// Check that a function of a given type can be applied to 77 /// Check that a function of a given type can be applied to
54 /// actuals. 78 /// actuals.
55 _checkApply(type, actuals) => JS( 79 _checkApply(type, actuals) => JS(
56 '', 80 '',
57 '''(() => { 81 '''(() => {
(...skipping 24 matching lines...) Expand all
82 if (names.length == 0) return false; 106 if (names.length == 0) return false;
83 for (var name of names) { 107 for (var name of names) {
84 if (!($hasOwnProperty.call($type.named, name))) { 108 if (!($hasOwnProperty.call($type.named, name))) {
85 return false; 109 return false;
86 } 110 }
87 $check(opts[name], $type.named[name]); 111 $check(opts[name], $type.named[name]);
88 } 112 }
89 return true; 113 return true;
90 })()'''); 114 })()''');
91 115
92 Symbol _dartSymbol(name) => 116 _toSymbolName(symbol) => JS(
93 JS('', '#(#.new(#.toString()))', const_, Symbol, name); 117 '',
118 '''(() => {
119 let str = $symbol.toString();
120 // Strip leading 'Symbol(' and trailing ')'
121 return str.substring(7, str.length-1);
122 })()''');
123
124 _toDisplayName(name) => JS(
125 '',
126 '''(() => {
127 // Names starting with _ are escaped names used to disambiguate Dart and
128 // JS names.
129 if ($name[0] === '_') {
130 // Inverse of
131 switch($name) {
132 case '_get':
133 return '[]';
134 case '_set':
135 return '[]=';
136 case '_negate':
137 return 'unary-';
138 case '_constructor':
139 case '_prototype':
140 return $name.substring(1);
141 }
142 }
143 return $name;
144 })()''');
145
146 Symbol _dartSymbol(name) {
147 return (JS('bool', 'typeof # === "symbol"', name))
148 ? JS('', '#(new #.es6(#, #))', const_, _internal.Symbol,
149 _toSymbolName(name), name)
150 : JS('', '#(#.new(#))', const_, Symbol, _toDisplayName(name));
151 }
94 152
95 /// Extracts the named argument array from a list of arguments, and returns it. 153 /// Extracts the named argument array from a list of arguments, and returns it.
96 // TODO(jmesserly): we need to handle named arguments better. 154 // TODO(jmesserly): we need to handle named arguments better.
97 extractNamedArgs(args) { 155 extractNamedArgs(args) {
98 if (JS('bool', '#.length > 0', args)) { 156 if (JS('bool', '#.length > 0', args)) {
99 var last = JS('', '#[#.length - 1]', args, args); 157 var last = JS('', '#[#.length - 1]', args, args);
100 if (JS( 158 if (JS(
101 'bool', '# != null && #.__proto__ === Object.prototype', last, last)) { 159 'bool', '# != null && #.__proto__ === Object.prototype', last, last)) {
102 return JS('', '#.pop()', args); 160 return JS('', '#.pop()', args);
103 } 161 }
(...skipping 10 matching lines...) Expand all
114 172
115 function callNSM() { 173 function callNSM() {
116 return $noSuchMethod(originalTarget, new $InvocationImpl( 174 return $noSuchMethod(originalTarget, new $InvocationImpl(
117 $name, $args, 175 $name, $args,
118 {namedArguments: $extractNamedArgs($args), isMethod: true})); 176 {namedArguments: $extractNamedArgs($args), isMethod: true}));
119 } 177 }
120 if (!($f instanceof Function)) { 178 if (!($f instanceof Function)) {
121 // We're not a function (and hence not a method either) 179 // We're not a function (and hence not a method either)
122 // Grab the `call` method if it's not a function. 180 // Grab the `call` method if it's not a function.
123 if ($f != null) { 181 if ($f != null) {
124 $ftype = $getMethodType($f, 'call'); 182 $ftype = $getMethodType($getType($f), 'call');
125 $f = $f.call; 183 $f = $f.call;
126 } 184 }
127 if (!($f instanceof Function)) { 185 if (!($f instanceof Function)) {
128 return callNSM(); 186 return callNSM();
129 } 187 }
130 } 188 }
131 // If f is a function, but not a method (no method type) 189 // If f is a function, but not a method (no method type)
132 // then it should have been a function valued field, so 190 // then it should have been a function valued field, so
133 // get the type from the function. 191 // get the type from the function.
134 if ($ftype === void 0) { 192 if ($ftype === void 0) {
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
296 } 354 }
297 355
298 /// Shared code for dsend, dindex, and dsetindex. 356 /// Shared code for dsend, dindex, and dsetindex.
299 _callMethod(obj, name, typeArgs, args, displayName) { 357 _callMethod(obj, name, typeArgs, args, displayName) {
300 var symbol = _canonicalMember(obj, name); 358 var symbol = _canonicalMember(obj, name);
301 if (symbol == null) { 359 if (symbol == null) {
302 return noSuchMethod( 360 return noSuchMethod(
303 obj, new InvocationImpl(displayName, args, isMethod: true)); 361 obj, new InvocationImpl(displayName, args, isMethod: true));
304 } 362 }
305 var f = obj != null ? JS('', '#[#]', obj, symbol) : null; 363 var f = obj != null ? JS('', '#[#]', obj, symbol) : null;
306 var ftype = getMethodType(obj, symbol); 364 var type = getType(obj);
365 var ftype = getMethodType(type, symbol);
366 // No such method if dart object and ftype is missing.
307 return _checkAndCall(f, ftype, obj, typeArgs, args, displayName); 367 return _checkAndCall(f, ftype, obj, typeArgs, args, displayName);
308 } 368 }
309 369
310 dsend(obj, method, @rest args) => _callMethod(obj, method, null, args, method); 370 dsend(obj, method, @rest args) => _callMethod(obj, method, null, args, method);
311 371
312 dgsend(obj, typeArgs, method, @rest args) => 372 dgsend(obj, typeArgs, method, @rest args) =>
313 _callMethod(obj, method, typeArgs, args, method); 373 _callMethod(obj, method, typeArgs, args, method);
314 374
315 dindex(obj, index) => 375 dindex(obj, index) =>
316 _callMethod(obj, '_get', null, JS('', '[#]', index), '[]'); 376 _callMethod(obj, '_get', null, JS('', '[#]', index), '[]');
(...skipping 524 matching lines...) Expand 10 before | Expand all | Expand 10 after
841 name = '+' + name; 901 name = '+' + name;
842 } 902 }
843 return name; 903 return name;
844 } 904 }
845 905
846 /// Emulates the implicit "loadLibrary" function provided by a deferred library. 906 /// Emulates the implicit "loadLibrary" function provided by a deferred library.
847 /// 907 ///
848 /// Libraries are not actually deferred in DDC, so this just returns a future 908 /// Libraries are not actually deferred in DDC, so this just returns a future
849 /// that completes immediately. 909 /// that completes immediately.
850 Future loadLibrary() => new Future.value(); 910 Future loadLibrary() => new Future.value();
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698