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 part of dart2js.js_emitter; | 5 part of dart2js.js_emitter; |
6 | 6 |
7 class NsmEmitter extends CodeEmitterHelper { | 7 class NsmEmitter extends CodeEmitterHelper { |
8 final List<Selector> trivialNsmHandlers = <Selector>[]; | 8 final List<Selector> trivialNsmHandlers = <Selector>[]; |
9 | 9 |
10 /// If this is true then we can generate the noSuchMethod handlers at startup | 10 /// If this is true then we can generate the noSuchMethod handlers at startup |
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
271 'diffEncoding': js.string('$diffEncoding')})); | 271 'diffEncoding': js.string('$diffEncoding')})); |
272 if (!minify) { | 272 if (!minify) { |
273 statements.add(js.statement('var longNames = #longs.split(",")', | 273 statements.add(js.statement('var longNames = #longs.split(",")', |
274 {'longs': js.string(longs.join(','))})); | 274 {'longs': js.string(longs.join(','))})); |
275 } | 275 } |
276 statements.add(js.statement( | 276 statements.add(js.statement( |
277 'if (objectClassObject instanceof Array)' | 277 'if (objectClassObject instanceof Array)' |
278 ' objectClassObject = objectClassObject[1];')); | 278 ' objectClassObject = objectClassObject[1];')); |
279 } | 279 } |
280 | 280 |
281 List<jsAst.Expression> sliceOffsetArguments = | 281 dynamic isIntercepted = // jsAst.Expression or bool. |
282 firstNormalSelector == 0 | 282 firstNormalSelector == 0 |
283 ? [] | 283 ? false |
284 : (firstNormalSelector == shorts.length | 284 : firstNormalSelector == shorts.length |
285 ? [js.number(1)] | 285 ? true |
286 : [js('(j < #) ? 1 : 0', js.number(firstNormalSelector))]); | 286 : js('j < #', js.number(firstNormalSelector)); |
287 | |
288 var sliceOffsetParams = sliceOffsetArguments.isEmpty ? [] : ['sliceOffset']; | |
289 | 287 |
290 statements.add(js.statement(''' | 288 statements.add(js.statement(''' |
291 // If we are loading a deferred library the object class will not be in | 289 // If we are loading a deferred library the object class will not be in |
292 // the collectedClasses so objectClassObject is undefined, and we skip | 290 // the collectedClasses so objectClassObject is undefined, and we skip |
293 // setting up the names. | 291 // setting up the names. |
294 if (objectClassObject) { | 292 if (objectClassObject) { |
295 for (var j = 0; j < shortNames.length; j++) { | 293 for (var j = 0; j < shortNames.length; j++) { |
296 var type = 0; | 294 var type = 0; |
297 var short = shortNames[j]; | 295 var shortName = shortNames[j]; |
298 if (short[0] == "${namer.getterPrefix[0]}") type = 1; | 296 if (shortName[0] == "${namer.getterPrefix[0]}") type = 1; |
299 if (short[0] == "${namer.setterPrefix[0]}") type = 2; | 297 if (shortName[0] == "${namer.setterPrefix[0]}") type = 2; |
300 // Generate call to: | 298 // Generate call to: |
301 // | 299 // |
302 // createInvocationMirror(String name, internalName, type, | 300 // createInvocationMirror(String name, internalName, type, |
303 // arguments, argumentNames) | 301 // arguments, argumentNames) |
304 // | 302 // |
305 objectClassObject[short] = (function(name, short, | 303 |
306 type, #sliceOffsetParams) { | 304 // This 'if' is either a static choice or dynamic choice depending on |
307 return function() { | 305 // [isIntercepted]. |
308 return this.#noSuchMethodName(this, | 306 if (#isIntercepted) { |
309 #createInvocationMirror(name, short, type, | 307 objectClassObject[shortName] = |
310 Array.prototype.slice.call(arguments, | 308 (function(name, shortName, type) { |
311 #sliceOffsetParams), | 309 return function(receiver) { |
312 [])); | 310 return this.#noSuchMethodName( |
313 } | 311 receiver, |
314 })(#names[j], short, type, #sliceOffsetArguments); | 312 #createInvocationMirror(name, shortName, type, |
| 313 // Create proper Array with all arguments except first |
| 314 // (receiver). |
| 315 Array.prototype.slice.call(arguments, 1), |
| 316 [])); |
| 317 } |
| 318 })(#names[j], shortName, type); |
| 319 } else { |
| 320 objectClassObject[shortName] = |
| 321 (function(name, shortName, type) { |
| 322 return function() { |
| 323 return this.#noSuchMethodName( |
| 324 // Object.noSuchMethodName ignores the explicit receiver |
| 325 // argument. We could pass anything in place of [this]. |
| 326 this, |
| 327 #createInvocationMirror(name, shortName, type, |
| 328 // Create proper Array with all arguments. |
| 329 Array.prototype.slice.call(arguments, 0), |
| 330 [])); |
| 331 } |
| 332 })(#names[j], shortName, type); |
| 333 } |
315 } | 334 } |
316 }''', { | 335 }''', { |
317 'sliceOffsetParams': sliceOffsetParams, | |
318 'noSuchMethodName': namer.noSuchMethodName, | 336 'noSuchMethodName': namer.noSuchMethodName, |
319 'createInvocationMirror': createInvocationMirror, | 337 'createInvocationMirror': createInvocationMirror, |
320 'names': minify ? 'shortNames' : 'longNames', | 338 'names': minify ? 'shortNames' : 'longNames', |
321 'sliceOffsetArguments': sliceOffsetArguments})); | 339 'isIntercepted': isIntercepted})); |
322 | 340 |
323 return statements; | 341 return statements; |
324 } | 342 } |
325 } | 343 } |
OLD | NEW |