| 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 // TODO(ahe): Share these with js_helper.dart. | 7 // TODO(ahe): Share these with js_helper.dart. |
| 8 const FUNCTION_INDEX = 0; | 8 const FUNCTION_INDEX = 0; |
| 9 const NAME_INDEX = 1; | 9 const NAME_INDEX = 1; |
| 10 const CALL_NAME_INDEX = 2; | 10 const CALL_NAME_INDEX = 2; |
| (...skipping 436 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 447 'processStatics': processStatics, | 447 'processStatics': processStatics, |
| 448 'incrementalSupport': incrementalSupport, | 448 'incrementalSupport': incrementalSupport, |
| 449 'addStubs': addStubs, | 449 'addStubs': addStubs, |
| 450 'tearOffCode': tearOffCode, | 450 'tearOffCode': tearOffCode, |
| 451 'init': init, | 451 'init': init, |
| 452 'finishClasses': finishClasses, | 452 'finishClasses': finishClasses, |
| 453 'needsClassSupport': oldEmitter.needsClassSupport, | 453 'needsClassSupport': oldEmitter.needsClassSupport, |
| 454 'needsStructuredMemberInfo': oldEmitter.needsStructuredMemberInfo}); | 454 'needsStructuredMemberInfo': oldEmitter.needsStructuredMemberInfo}); |
| 455 } | 455 } |
| 456 | 456 |
| 457 | |
| 458 List<jsAst.Statement> buildTearOffCode(JavaScriptBackend backend) { | |
| 459 Namer namer = backend.namer; | |
| 460 Compiler compiler = backend.compiler; | |
| 461 | |
| 462 Element closureFromTearOff = backend.findHelper('closureFromTearOff'); | |
| 463 String tearOffAccessText; | |
| 464 jsAst.Expression tearOffAccessExpression; | |
| 465 String tearOffGlobalObjectName; | |
| 466 String tearOffGlobalObject; | |
| 467 if (closureFromTearOff != null) { | |
| 468 // We need both the AST that references [closureFromTearOff] and a string | |
| 469 // for the NoCsp version that constructs a function. | |
| 470 tearOffAccessExpression = | |
| 471 backend.emitter.staticFunctionAccess(closureFromTearOff); | |
| 472 tearOffAccessText = | |
| 473 jsAst.prettyPrint(tearOffAccessExpression, compiler).getText(); | |
| 474 tearOffGlobalObjectName = tearOffGlobalObject = | |
| 475 namer.globalObjectFor(closureFromTearOff); | |
| 476 } else { | |
| 477 // Default values for mocked-up test libraries. | |
| 478 tearOffAccessText = | |
| 479 r'''function() { throw 'Helper \'closureFromTearOff\' missing.' }'''; | |
| 480 tearOffAccessExpression = js(tearOffAccessText); | |
| 481 tearOffGlobalObjectName = 'MissingHelperFunction'; | |
| 482 tearOffGlobalObject = '($tearOffAccessText())'; | |
| 483 } | |
| 484 | |
| 485 jsAst.Statement tearOffGetter; | |
| 486 if (!compiler.useContentSecurityPolicy) { | |
| 487 // This template is uncached because it is constructed from code fragments | |
| 488 // that can change from compilation to compilation. Some of these could be | |
| 489 // avoided, except for the string literals that contain the compiled access | |
| 490 // path to 'closureFromTearOff'. | |
| 491 tearOffGetter = js.uncachedStatementTemplate(''' | |
| 492 function tearOffGetter(funcs, reflectionInfo, name, isIntercepted) { | |
| 493 return isIntercepted | |
| 494 ? new Function("funcs", "reflectionInfo", "name", | |
| 495 "$tearOffGlobalObjectName", "c", | |
| 496 "return function tearOff_" + name + (functionCounter++)+ "(x)
{" + | |
| 497 "if (c === null) c = $tearOffAccessText(" + | |
| 498 "this, funcs, reflectionInfo, false, [x], name);" + | |
| 499 "return new c(this, funcs[0], x, name);" + | |
| 500 "}")(funcs, reflectionInfo, name, $tearOffGlobalObject, null) | |
| 501 : new Function("funcs", "reflectionInfo", "name", | |
| 502 "$tearOffGlobalObjectName", "c", | |
| 503 "return function tearOff_" + name + (functionCounter++)+ "() {
" + | |
| 504 "if (c === null) c = $tearOffAccessText(" + | |
| 505 "this, funcs, reflectionInfo, false, [], name);" + | |
| 506 "return new c(this, funcs[0], null, name);" + | |
| 507 "}")(funcs, reflectionInfo, name, $tearOffGlobalObject, null); | |
| 508 }''').instantiate([]); | |
| 509 } else { | |
| 510 tearOffGetter = js.statement(''' | |
| 511 function tearOffGetter(funcs, reflectionInfo, name, isIntercepted) { | |
| 512 var cache = null; | |
| 513 return isIntercepted | |
| 514 ? function(x) { | |
| 515 if (cache === null) cache = #( | |
| 516 this, funcs, reflectionInfo, false, [x], name); | |
| 517 return new cache(this, funcs[0], x, name); | |
| 518 } | |
| 519 : function() { | |
| 520 if (cache === null) cache = #( | |
| 521 this, funcs, reflectionInfo, false, [], name); | |
| 522 return new cache(this, funcs[0], null, name); | |
| 523 }; | |
| 524 }''', [tearOffAccessExpression, tearOffAccessExpression]); | |
| 525 } | |
| 526 | |
| 527 jsAst.Statement tearOff = js.statement(''' | |
| 528 function tearOff(funcs, reflectionInfo, isStatic, name, isIntercepted) { | |
| 529 var cache; | |
| 530 return isStatic | |
| 531 ? function() { | |
| 532 if (cache === void 0) cache = #tearOff( | |
| 533 this, funcs, reflectionInfo, true, [], name).prototype; | |
| 534 return cache; | |
| 535 } | |
| 536 : tearOffGetter(funcs, reflectionInfo, name, isIntercepted); | |
| 537 }''', {'tearOff': tearOffAccessExpression}); | |
| 538 | |
| 539 return <jsAst.Statement>[tearOffGetter, tearOff]; | |
| 540 } | |
| 541 | |
| 542 String readString(String array, String index) { | 457 String readString(String array, String index) { |
| 543 return readChecked( | 458 return readChecked( |
| 544 array, index, 'result != null && typeof result != "string"', 'string'); | 459 array, index, 'result != null && typeof result != "string"', 'string'); |
| 545 } | 460 } |
| 546 | 461 |
| 547 String readInt(String array, String index) { | 462 String readInt(String array, String index) { |
| 548 return readChecked( | 463 return readChecked( |
| 549 array, index, | 464 array, index, |
| 550 'result != null && (typeof result != "number" || (result|0) !== result)', | 465 'result != null && (typeof result != "number" || (result|0) !== result)', |
| 551 'int'); | 466 'int'); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 566 (function() { | 481 (function() { |
| 567 var result = $array[$index]; | 482 var result = $array[$index]; |
| 568 if ($check) { | 483 if ($check) { |
| 569 throw new Error( | 484 throw new Error( |
| 570 name + ": expected value of type \'$type\' at index " + ($index) + | 485 name + ": expected value of type \'$type\' at index " + ($index) + |
| 571 " but got " + (typeof result)); | 486 " but got " + (typeof result)); |
| 572 } | 487 } |
| 573 return result; | 488 return result; |
| 574 })()'''; | 489 })()'''; |
| 575 } | 490 } |
| OLD | NEW |