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

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

Powered by Google App Engine
This is Rietveld 408576698