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

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, 10 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 objType = getType(obj);
54 var setterType = getSetterType(objType, f);
55 if (JS('bool', '# != void 0', setterType)) {
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]', setterType))) {
59 return JS('', '#[#] = #', obj, f, value);
60 }
61 } else {
62 var fieldType = getFieldType(objType, f);
63 // TODO(jacobr): add metadata tracking which fields are final and throw
64 // if a setter is called on a final field.
65 if (JS('bool', '# != void 0', fieldType)) {
66 // TODO(jacobr): throw a type error instead of a NoSuchMethodError if
67 // the type of the field doesn't match.
68 if (instanceOfOrNull(value, fieldType)) {
69 return JS('', '#[#] = #', obj, f, value);
70 }
71 }
72 }
48 } 73 }
49 return noSuchMethod( 74 return noSuchMethod(
50 obj, new InvocationImpl(field, JS('', '[#]', value), isSetter: true)); 75 obj, new InvocationImpl(field, JS('', '[#]', value), isSetter: true));
51 } 76 }
52 77
53 /// Check that a function of a given type can be applied to 78 /// Check that a function of a given type can be applied to
54 /// actuals. 79 /// actuals.
55 _checkApply(type, actuals) => JS( 80 _checkApply(type, actuals) => JS(
56 '', 81 '',
57 '''(() => { 82 '''(() => {
(...skipping 24 matching lines...) Expand all
82 if (names.length == 0) return false; 107 if (names.length == 0) return false;
83 for (var name of names) { 108 for (var name of names) {
84 if (!($hasOwnProperty.call($type.named, name))) { 109 if (!($hasOwnProperty.call($type.named, name))) {
85 return false; 110 return false;
86 } 111 }
87 $check(opts[name], $type.named[name]); 112 $check(opts[name], $type.named[name]);
88 } 113 }
89 return true; 114 return true;
90 })()'''); 115 })()''');
91 116
92 Symbol _dartSymbol(name) => 117 _toSymbolName(symbol) => JS(
93 JS('', '#(#.new(#.toString()))', const_, Symbol, name); 118 '',
119 '''(() => {
120 let str = $symbol.toString();
121 // Strip leading 'Symbol(' and trailing ')'
122 return str.substring(7, str.length-1);
123 })()''');
124
125 _toDisplayName(name) => JS(
126 '',
127 '''(() => {
128 // Names starting with _ are escaped names used to disambiguate Dart and
129 // JS names.
130 if ($name[0] === '_') {
131 // Inverse of
132 switch($name) {
133 case '_get':
134 return '[]';
135 case '_set':
136 return '[]=';
137 case '_negate':
138 return 'unary-';
139 case '_constructor':
140 case '_prototype':
141 return $name.substring(1);
142 }
143 }
144 return $name;
145 })()''');
146
147 Symbol _dartSymbol(name) {
148 return (JS('bool', 'typeof # === "symbol"', name))
149 ? JS('', '#(new #.es6(#, #))', const_, _internal.Symbol,
150 _toSymbolName(name), name)
151 : JS('', '#(#.new(#))', const_, Symbol, _toDisplayName(name));
152 }
94 153
95 /// Extracts the named argument array from a list of arguments, and returns it. 154 /// Extracts the named argument array from a list of arguments, and returns it.
96 // TODO(jmesserly): we need to handle named arguments better. 155 // TODO(jmesserly): we need to handle named arguments better.
97 extractNamedArgs(args) { 156 extractNamedArgs(args) {
98 if (JS('bool', '#.length > 0', args)) { 157 if (JS('bool', '#.length > 0', args)) {
99 var last = JS('', '#[#.length - 1]', args, args); 158 var last = JS('', '#[#.length - 1]', args, args);
100 if (JS( 159 if (JS(
101 'bool', '# != null && #.__proto__ === Object.prototype', last, last)) { 160 'bool', '# != null && #.__proto__ === Object.prototype', last, last)) {
102 return JS('', '#.pop()', args); 161 return JS('', '#.pop()', args);
103 } 162 }
(...skipping 10 matching lines...) Expand all
114 173
115 function callNSM() { 174 function callNSM() {
116 return $noSuchMethod(originalTarget, new $InvocationImpl( 175 return $noSuchMethod(originalTarget, new $InvocationImpl(
117 $name, $args, 176 $name, $args,
118 {namedArguments: $extractNamedArgs($args), isMethod: true})); 177 {namedArguments: $extractNamedArgs($args), isMethod: true}));
119 } 178 }
120 if (!($f instanceof Function)) { 179 if (!($f instanceof Function)) {
121 // We're not a function (and hence not a method either) 180 // We're not a function (and hence not a method either)
122 // Grab the `call` method if it's not a function. 181 // Grab the `call` method if it's not a function.
123 if ($f != null) { 182 if ($f != null) {
124 $ftype = $getMethodType($f, 'call'); 183 $ftype = $getMethodType($getType($f), 'call');
125 $f = $f.call; 184 $f = $f.call;
126 } 185 }
127 if (!($f instanceof Function)) { 186 if (!($f instanceof Function)) {
128 return callNSM(); 187 return callNSM();
129 } 188 }
130 } 189 }
131 // If f is a function, but not a method (no method type) 190 // If f is a function, but not a method (no method type)
132 // then it should have been a function valued field, so 191 // then it should have been a function valued field, so
133 // get the type from the function. 192 // get the type from the function.
134 if ($ftype === void 0) { 193 if ($ftype === void 0) {
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
296 } 355 }
297 356
298 /// Shared code for dsend, dindex, and dsetindex. 357 /// Shared code for dsend, dindex, and dsetindex.
299 _callMethod(obj, name, typeArgs, args, displayName) { 358 _callMethod(obj, name, typeArgs, args, displayName) {
300 var symbol = _canonicalMember(obj, name); 359 var symbol = _canonicalMember(obj, name);
301 if (symbol == null) { 360 if (symbol == null) {
302 return noSuchMethod( 361 return noSuchMethod(
303 obj, new InvocationImpl(displayName, args, isMethod: true)); 362 obj, new InvocationImpl(displayName, args, isMethod: true));
304 } 363 }
305 var f = obj != null ? JS('', '#[#]', obj, symbol) : null; 364 var f = obj != null ? JS('', '#[#]', obj, symbol) : null;
306 var ftype = getMethodType(obj, symbol); 365 var type = getType(obj);
366 var ftype = getMethodType(type, symbol);
367 // No such method if dart object and ftype is missing.
307 return _checkAndCall(f, ftype, obj, typeArgs, args, displayName); 368 return _checkAndCall(f, ftype, obj, typeArgs, args, displayName);
308 } 369 }
309 370
310 dsend(obj, method, @rest args) => _callMethod(obj, method, null, args, method); 371 dsend(obj, method, @rest args) => _callMethod(obj, method, null, args, method);
311 372
312 dgsend(obj, typeArgs, method, @rest args) => 373 dgsend(obj, typeArgs, method, @rest args) =>
313 _callMethod(obj, method, typeArgs, args, method); 374 _callMethod(obj, method, typeArgs, args, method);
314 375
315 dindex(obj, index) => 376 dindex(obj, index) =>
316 _callMethod(obj, '_get', null, JS('', '[#]', index), '[]'); 377 _callMethod(obj, '_get', null, JS('', '[#]', index), '[]');
(...skipping 524 matching lines...) Expand 10 before | Expand all | Expand 10 after
841 name = '+' + name; 902 name = '+' + name;
842 } 903 }
843 return name; 904 return name;
844 } 905 }
845 906
846 /// Emulates the implicit "loadLibrary" function provided by a deferred library. 907 /// Emulates the implicit "loadLibrary" function provided by a deferred library.
847 /// 908 ///
848 /// Libraries are not actually deferred in DDC, so this just returns a future 909 /// Libraries are not actually deferred in DDC, so this just returns a future
849 /// that completes immediately. 910 /// that completes immediately.
850 Future loadLibrary() => new Future.value(); 911 Future loadLibrary() => new Future.value();
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698