OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 dart2js.js_emitter.interceptor_stub_generator; | 5 library dart2js.js_emitter.interceptor_stub_generator; |
6 | 6 |
7 import 'package:js_runtime/shared/embedded_names.dart' as embeddedNames; | 7 import 'package:js_runtime/shared/embedded_names.dart' as embeddedNames; |
8 | 8 |
9 import '../common_elements.dart'; | 9 import '../common_elements.dart'; |
10 import '../constants/values.dart'; | 10 import '../constants/values.dart'; |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
146 | 146 |
147 /// Note: there are two number classes in play: Dart's [num], | 147 /// Note: there are two number classes in play: Dart's [num], |
148 /// and JavaScript's Number (typeof receiver == 'number'). This | 148 /// and JavaScript's Number (typeof receiver == 'number'). This |
149 /// is the fallback used when we have determined that receiver | 149 /// is the fallback used when we have determined that receiver |
150 /// is a JavaScript Number. | 150 /// is a JavaScript Number. |
151 jsAst.Expression interceptorForNumber = interceptorFor(hasDouble | 151 jsAst.Expression interceptorForNumber = interceptorFor(hasDouble |
152 ? _commonElements.jsDoubleClass | 152 ? _commonElements.jsDoubleClass |
153 : _commonElements.jsNumberClass); | 153 : _commonElements.jsNumberClass); |
154 | 154 |
155 if (hasInt) { | 155 if (hasInt) { |
156 whenNumber = js.statement( | 156 whenNumber = js.statement('''{ |
157 '''{ | |
158 if (Math.floor(receiver) == receiver) return #; | 157 if (Math.floor(receiver) == receiver) return #; |
159 return #; | 158 return #; |
160 }''', | 159 }''', |
161 [interceptorFor(_commonElements.jsIntClass), interceptorForNumber]); | 160 [interceptorFor(_commonElements.jsIntClass), interceptorForNumber]); |
162 } else { | 161 } else { |
163 whenNumber = js.statement('return #', interceptorForNumber); | 162 whenNumber = js.statement('return #', interceptorForNumber); |
164 } | 163 } |
165 statements | 164 statements |
166 .add(js.statement('if (typeof receiver == "number") #;', whenNumber)); | 165 .add(js.statement('if (typeof receiver == "number") #;', whenNumber)); |
167 } | 166 } |
(...skipping 12 matching lines...) Expand all Loading... |
180 if (hasBool) { | 179 if (hasBool) { |
181 statements.add(buildInterceptorCheck(_commonElements.jsBoolClass)); | 180 statements.add(buildInterceptorCheck(_commonElements.jsBoolClass)); |
182 } | 181 } |
183 // TODO(ahe): It might be faster to check for Array before | 182 // TODO(ahe): It might be faster to check for Array before |
184 // function and bool. | 183 // function and bool. |
185 if (hasArray) { | 184 if (hasArray) { |
186 statements.add(buildInterceptorCheck(_commonElements.jsArrayClass)); | 185 statements.add(buildInterceptorCheck(_commonElements.jsArrayClass)); |
187 } | 186 } |
188 | 187 |
189 if (hasNative) { | 188 if (hasNative) { |
190 statements.add(js.statement( | 189 statements.add(js.statement(r'''{ |
191 r'''{ | |
192 if (typeof receiver != "object") { | 190 if (typeof receiver != "object") { |
193 if (typeof receiver == "function" ) return #; | 191 if (typeof receiver == "function" ) return #; |
194 return receiver; | 192 return receiver; |
195 } | 193 } |
196 if (receiver instanceof #) return receiver; | 194 if (receiver instanceof #) return receiver; |
197 return #(receiver); | 195 return #(receiver); |
198 }''', | 196 }''', [ |
199 [ | 197 interceptorFor(_commonElements.jsJavaScriptFunctionClass), |
200 interceptorFor(_commonElements.jsJavaScriptFunctionClass), | 198 _emitter.constructorAccess(_commonElements.objectClass), |
201 _emitter.constructorAccess(_commonElements.objectClass), | 199 _emitter |
202 _emitter.staticFunctionAccess( | 200 .staticFunctionAccess(_commonElements.getNativeInterceptorMethod) |
203 _commonElements.getNativeInterceptorMethod) | 201 ])); |
204 ])); | |
205 } else { | 202 } else { |
206 ClassEntity jsUnknown = _commonElements.jsUnknownJavaScriptObjectClass; | 203 ClassEntity jsUnknown = _commonElements.jsUnknownJavaScriptObjectClass; |
207 if (_codegenWorldBuilder.directlyInstantiatedClasses | 204 if (_codegenWorldBuilder.directlyInstantiatedClasses |
208 .contains(jsUnknown)) { | 205 .contains(jsUnknown)) { |
209 statements.add(js.statement('if (!(receiver instanceof #)) return #;', [ | 206 statements.add(js.statement('if (!(receiver instanceof #)) return #;', [ |
210 _emitter.constructorAccess(_commonElements.objectClass), | 207 _emitter.constructorAccess(_commonElements.objectClass), |
211 interceptorFor(jsUnknown) | 208 interceptorFor(jsUnknown) |
212 ])); | 209 ])); |
213 } | 210 } |
214 | 211 |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
332 } | 329 } |
333 | 330 |
334 if (containsString) { | 331 if (containsString) { |
335 typeCheck = orExp(typeCheck, js('typeof receiver == "string"')); | 332 typeCheck = orExp(typeCheck, js('typeof receiver == "string"')); |
336 } | 333 } |
337 | 334 |
338 if (containsJsIndexable) { | 335 if (containsJsIndexable) { |
339 typeCheck = orExp(typeCheck, indexableCheck); | 336 typeCheck = orExp(typeCheck, indexableCheck); |
340 } | 337 } |
341 | 338 |
342 return js.statement( | 339 return js.statement(''' |
343 ''' | |
344 if (typeof a0 === "number") | 340 if (typeof a0 === "number") |
345 if (#) | 341 if (#) |
346 if ((a0 >>> 0) === a0 && a0 < receiver.length) | 342 if ((a0 >>> 0) === a0 && a0 < receiver.length) |
347 return receiver[a0]; | 343 return receiver[a0]; |
348 ''', | 344 ''', typeCheck); |
349 typeCheck); | |
350 } else { | 345 } else { |
351 jsAst.Expression typeCheck; | 346 jsAst.Expression typeCheck; |
352 if (containsArray) { | 347 if (containsArray) { |
353 typeCheck = arrayCheck; | 348 typeCheck = arrayCheck; |
354 } | 349 } |
355 | 350 |
356 if (containsJsIndexable) { | 351 if (containsJsIndexable) { |
357 typeCheck = orExp(typeCheck, indexableCheck); | 352 typeCheck = orExp(typeCheck, indexableCheck); |
358 } | 353 } |
359 | 354 |
360 return js.statement( | 355 return js.statement(r''' |
361 r''' | |
362 if (typeof a0 === "number") | 356 if (typeof a0 === "number") |
363 if (# && !receiver.immutable$list && | 357 if (# && !receiver.immutable$list && |
364 (a0 >>> 0) === a0 && a0 < receiver.length) | 358 (a0 >>> 0) === a0 && a0 < receiver.length) |
365 return receiver[a0] = a1; | 359 return receiver[a0] = a1; |
366 ''', | 360 ''', typeCheck); |
367 typeCheck); | |
368 } | 361 } |
369 } | 362 } |
370 return null; | 363 return null; |
371 } | 364 } |
372 | 365 |
373 jsAst.Expression generateOneShotInterceptor(jsAst.Name name) { | 366 jsAst.Expression generateOneShotInterceptor(jsAst.Name name) { |
374 Selector selector = | 367 Selector selector = |
375 _oneShotInterceptorData.getOneShotInterceptorSelector(name); | 368 _oneShotInterceptorData.getOneShotInterceptorSelector(name); |
376 Set<ClassEntity> classes = | 369 Set<ClassEntity> classes = |
377 _interceptorData.getInterceptedClassesOn(selector.name, _closedWorld); | 370 _interceptorData.getInterceptedClassesOn(selector.name, _closedWorld); |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
446 } | 439 } |
447 | 440 |
448 var map = new jsAst.ObjectInitializer(properties); | 441 var map = new jsAst.ObjectInitializer(properties); |
449 elements.add(map); | 442 elements.add(map); |
450 } | 443 } |
451 } | 444 } |
452 | 445 |
453 return new jsAst.ArrayInitializer(elements); | 446 return new jsAst.ArrayInitializer(elements); |
454 } | 447 } |
455 } | 448 } |
OLD | NEW |