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 dynamic isIntercepted = // jsAst.Expression or bool. | 281 List<jsAst.Expression> sliceOffsetArguments = |
282 firstNormalSelector == 0 | 282 firstNormalSelector == 0 |
283 ? false | 283 ? [] |
284 : firstNormalSelector == shorts.length | 284 : (firstNormalSelector == shorts.length |
285 ? true | 285 ? [js.number(1)] |
286 : js('j < #', js.number(firstNormalSelector)); | 286 : [js('(j < #) ? 1 : 0', js.number(firstNormalSelector))]); |
| 287 |
| 288 var sliceOffsetParams = sliceOffsetArguments.isEmpty ? [] : ['sliceOffset']; |
287 | 289 |
288 statements.add(js.statement(''' | 290 statements.add(js.statement(''' |
289 // If we are loading a deferred library the object class will not be in | 291 // If we are loading a deferred library the object class will not be in |
290 // the collectedClasses so objectClassObject is undefined, and we skip | 292 // the collectedClasses so objectClassObject is undefined, and we skip |
291 // setting up the names. | 293 // setting up the names. |
292 if (objectClassObject) { | 294 if (objectClassObject) { |
293 for (var j = 0; j < shortNames.length; j++) { | 295 for (var j = 0; j < shortNames.length; j++) { |
294 var type = 0; | 296 var type = 0; |
295 var shortName = shortNames[j]; | 297 var short = shortNames[j]; |
296 if (shortName[0] == "${namer.getterPrefix[0]}") type = 1; | 298 if (short[0] == "${namer.getterPrefix[0]}") type = 1; |
297 if (shortName[0] == "${namer.setterPrefix[0]}") type = 2; | 299 if (short[0] == "${namer.setterPrefix[0]}") type = 2; |
298 // Generate call to: | 300 // Generate call to: |
299 // | 301 // |
300 // createInvocationMirror(String name, internalName, type, | 302 // createInvocationMirror(String name, internalName, type, |
301 // arguments, argumentNames) | 303 // arguments, argumentNames) |
302 // | 304 // |
303 | 305 objectClassObject[short] = (function(name, short, |
304 // This 'if' is either a static choice or dynamic choice depending on | 306 type, #sliceOffsetParams) { |
305 // [isIntercepted]. | 307 return function() { |
306 if (#isIntercepted) { | 308 return this.#noSuchMethodName(this, |
307 objectClassObject[shortName] = | 309 #createInvocationMirror(name, short, type, |
308 (function(name, shortName, type) { | 310 Array.prototype.slice.call(arguments, |
309 return function(receiver) { | 311 #sliceOffsetParams), |
310 return this.#noSuchMethodName( | 312 [])); |
311 receiver, | 313 } |
312 #createInvocationMirror(name, shortName, type, | 314 })(#names[j], short, type, #sliceOffsetArguments); |
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 } | |
334 } | 315 } |
335 }''', { | 316 }''', { |
| 317 'sliceOffsetParams': sliceOffsetParams, |
336 'noSuchMethodName': namer.noSuchMethodName, | 318 'noSuchMethodName': namer.noSuchMethodName, |
337 'createInvocationMirror': createInvocationMirror, | 319 'createInvocationMirror': createInvocationMirror, |
338 'names': minify ? 'shortNames' : 'longNames', | 320 'names': minify ? 'shortNames' : 'longNames', |
339 'isIntercepted': isIntercepted})); | 321 'sliceOffsetArguments': sliceOffsetArguments})); |
340 | 322 |
341 return statements; | 323 return statements; |
342 } | 324 } |
343 } | 325 } |
OLD | NEW |