OLD | NEW |
---|---|
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 library _js_helper; | 5 library _js_helper; |
6 | 6 |
7 import 'dart:collection'; | 7 import 'dart:collection'; |
8 import 'dart:_isolate_helper' show | 8 import 'dart:_isolate_helper' show |
9 IsolateNatives, | 9 IsolateNatives, |
10 leaveJsAsync, | 10 leaveJsAsync, |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
176 | 176 |
177 _getCachedInvocation(Object object) { | 177 _getCachedInvocation(Object object) { |
178 var interceptor = getInterceptor(object); | 178 var interceptor = getInterceptor(object); |
179 var receiver = object; | 179 var receiver = object; |
180 var name = _internalName; | 180 var name = _internalName; |
181 var arguments = _arguments; | 181 var arguments = _arguments; |
182 // TODO(ngeoffray): If this functionality ever become performance | 182 // TODO(ngeoffray): If this functionality ever become performance |
183 // critical, we might want to dynamically change [interceptedNames] | 183 // critical, we might want to dynamically change [interceptedNames] |
184 // to be a JavaScript object with intercepted names as property | 184 // to be a JavaScript object with intercepted names as property |
185 // instead of a JavaScript array. | 185 // instead of a JavaScript array. |
186 // TODO(floitsch): we already add stubs (tear-off getters) as properties | |
187 // in init.interceptedNames. | |
karlklose
2014/04/01 08:32:23
Align indentation with TODO above.
floitsch
2014/04/01 14:03:19
Done.
| |
188 // Finish the transition and always use the object as hashtable. | |
186 bool isIntercepted = | 189 bool isIntercepted = |
187 JS('int', '#.indexOf(#)', interceptedNames, name) != -1; | 190 JS("bool", |
191 'Object.prototype.hasOwnProperty.call(init.interceptedNames, #) ||' | |
192 '#.indexOf(#) !== -1', | |
193 name, interceptedNames, name); | |
188 if (isIntercepted) { | 194 if (isIntercepted) { |
189 receiver = interceptor; | 195 receiver = interceptor; |
190 if (JS('bool', '# === #', object, interceptor)) { | 196 if (JS('bool', '# === #', object, interceptor)) { |
191 interceptor = null; | 197 interceptor = null; |
192 } | 198 } |
193 } else { | 199 } else { |
194 interceptor = null; | 200 interceptor = null; |
195 } | 201 } |
196 bool isCatchAll = false; | 202 bool isCatchAll = false; |
197 var method = JS('var', '#[#]', receiver, name); | 203 var method = JS('var', '#[#]', receiver, name); |
198 if (JS('bool', 'typeof # != "function"', method) ) { | 204 if (JS('bool', 'typeof # != "function"', method) ) { |
199 String baseName = _symbol_dev.Symbol.getName(memberName); | 205 String baseName = _symbol_dev.Symbol.getName(memberName); |
200 method = JS('', '#[# + "*"]', receiver, baseName); | 206 method = JS('', '#[# + "*"]', receiver, baseName); |
201 if (method == null) { | 207 if (method == null) { |
202 interceptor = getInterceptor(object); | 208 interceptor = getInterceptor(object); |
203 method = JS('', '#[# + "*"]', interceptor, baseName); | 209 method = JS('', '#[# + "*"]', interceptor, baseName); |
204 if (method != null) { | 210 if (method != null) { |
205 isIntercepted = true; | 211 isIntercepted = true; |
206 receiver = interceptor; | 212 receiver = interceptor; |
207 } else { | 213 } else { |
208 interceptor = null; | 214 interceptor = null; |
209 } | 215 } |
210 } | 216 } |
211 isCatchAll = true; | 217 isCatchAll = true; |
212 } | 218 } |
213 if (JS('bool', 'typeof # == "function"', method)) { | 219 if (JS('bool', 'typeof # == "function"', method)) { |
214 if (!hasReflectableProperty(method)) { | 220 // TODO(floitsch): bound or tear-off closure does not guarantee that the |
221 // function is reflectable. | |
karlklose
2014/04/01 08:32:23
Perhaps we should add a failing test to make sure
floitsch
2014/04/01 14:03:19
Filed 17939 and added test.
| |
222 bool isReflectable = hasReflectableProperty(method) || | |
223 object is BoundClosure || | |
224 object is TearOffClosure; | |
225 if (!isReflectable) { | |
215 throwInvalidReflectionError(_symbol_dev.Symbol.getName(memberName)); | 226 throwInvalidReflectionError(_symbol_dev.Symbol.getName(memberName)); |
216 } | 227 } |
217 if (isCatchAll) { | 228 if (isCatchAll) { |
218 return new CachedCatchAllInvocation( | 229 return new CachedCatchAllInvocation( |
219 name, method, isIntercepted, interceptor); | 230 name, method, isIntercepted, interceptor); |
220 } else { | 231 } else { |
221 return new CachedInvocation(name, method, isIntercepted, interceptor); | 232 return new CachedInvocation(name, method, isIntercepted, interceptor); |
222 } | 233 } |
223 } else { | 234 } else { |
224 // In this case, receiver doesn't implement name. So we should | 235 // In this case, receiver doesn't implement name. So we should |
(...skipping 1754 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1979 | 1990 |
1980 // Create a closure and "monkey" patch it with call stubs. | 1991 // Create a closure and "monkey" patch it with call stubs. |
1981 var trampoline = function; | 1992 var trampoline = function; |
1982 var isIntercepted = false; | 1993 var isIntercepted = false; |
1983 if (!isStatic) { | 1994 if (!isStatic) { |
1984 if (JS('bool', '#.length == 1', jsArguments)) { | 1995 if (JS('bool', '#.length == 1', jsArguments)) { |
1985 // Intercepted call. | 1996 // Intercepted call. |
1986 isIntercepted = true; | 1997 isIntercepted = true; |
1987 } | 1998 } |
1988 trampoline = forwardCallTo(receiver, function, isIntercepted); | 1999 trampoline = forwardCallTo(receiver, function, isIntercepted); |
2000 JS('', '#.\$reflectionInfo = #', trampoline, reflectionInfo); | |
1989 } else { | 2001 } else { |
1990 JS('', '#.\$name = #', prototype, propertyName); | 2002 JS('', '#.\$name = #', prototype, propertyName); |
1991 } | 2003 } |
1992 | 2004 |
1993 var signatureFunction; | 2005 var signatureFunction; |
1994 if (JS('bool', 'typeof # == "number"', functionType)) { | 2006 if (JS('bool', 'typeof # == "number"', functionType)) { |
1995 signatureFunction = | 2007 signatureFunction = |
1996 JS('', '(function(s){return function(){return init.metadata[s]}})(#)', | 2008 JS('', '(function(s){return function(){return init.metadata[s]}})(#)', |
1997 functionType); | 2009 functionType); |
1998 } else if (!isStatic | 2010 } else if (!isStatic |
(...skipping 17 matching lines...) Expand all Loading... | |
2016 JS('', '#[#] = #', prototype, callName, trampoline); | 2028 JS('', '#[#] = #', prototype, callName, trampoline); |
2017 for (int i = 1; i < functions.length; i++) { | 2029 for (int i = 1; i < functions.length; i++) { |
2018 var stub = functions[i]; | 2030 var stub = functions[i]; |
2019 var stubCallName = JS('String|Null', '#.\$callName', stub); | 2031 var stubCallName = JS('String|Null', '#.\$callName', stub); |
2020 if (stubCallName != null) { | 2032 if (stubCallName != null) { |
2021 JS('', '#[#] = #', prototype, stubCallName, | 2033 JS('', '#[#] = #', prototype, stubCallName, |
2022 isStatic ? stub : forwardCallTo(receiver, stub, isIntercepted)); | 2034 isStatic ? stub : forwardCallTo(receiver, stub, isIntercepted)); |
2023 } | 2035 } |
2024 } | 2036 } |
2025 | 2037 |
2026 JS('', '#["call*"] = #', prototype, function); | 2038 JS('', '#["call*"] = #', prototype, trampoline); |
floitsch
2014/03/31 20:12:01
I think this was always wrong, and just never hit.
| |
2027 | 2039 |
2028 return constructor; | 2040 return constructor; |
2029 } | 2041 } |
2030 | 2042 |
2031 static cspForwardCall(int arity, bool isSuperCall, String stubName, | 2043 static cspForwardCall(int arity, bool isSuperCall, String stubName, |
2032 function) { | 2044 function) { |
2033 var getSelf = RAW_DART_FUNCTION_REF(BoundClosure.selfOf); | 2045 var getSelf = RAW_DART_FUNCTION_REF(BoundClosure.selfOf); |
2034 // Handle intercepted stub-names with the default slow case. | 2046 // Handle intercepted stub-names with the default slow case. |
2035 if (isSuperCall) arity = -1; | 2047 if (isSuperCall) arity = -1; |
2036 switch (arity) { | 2048 switch (arity) { |
(...skipping 1283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3320 JS('', '#.addEventListener("error", #, false)', | 3332 JS('', '#.addEventListener("error", #, false)', |
3321 script, convertDartClosureToJS((event) { | 3333 script, convertDartClosureToJS((event) { |
3322 completer.completeError( | 3334 completer.completeError( |
3323 new DeferredLoadException("Loading $uri failed.")); | 3335 new DeferredLoadException("Loading $uri failed.")); |
3324 }, 1)); | 3336 }, 1)); |
3325 JS('', 'document.body.appendChild(#)', script); | 3337 JS('', 'document.body.appendChild(#)', script); |
3326 | 3338 |
3327 return completer.future; | 3339 return completer.future; |
3328 }); | 3340 }); |
3329 } | 3341 } |
OLD | NEW |