| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 rewrite_async; | 5 library rewrite_async; |
| 6 | 6 |
| 7 import 'dart:collection'; | 7 import 'dart:collection'; |
| 8 import 'dart:math' show max; | 8 import 'dart:math' show max; |
| 9 | 9 |
| 10 import 'package:js_runtime/shared/async_await_error_codes.dart' as error_codes; | 10 import 'package:js_runtime/shared/async_await_error_codes.dart' as error_codes; |
| (...skipping 1634 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1645 | 1645 |
| 1646 class AsyncRewriter extends AsyncRewriterBase { | 1646 class AsyncRewriter extends AsyncRewriterBase { |
| 1647 bool get isAsync => true; | 1647 bool get isAsync => true; |
| 1648 | 1648 |
| 1649 /// The Completer that will finish an async function. | 1649 /// The Completer that will finish an async function. |
| 1650 /// | 1650 /// |
| 1651 /// Not used for sync* or async* functions. | 1651 /// Not used for sync* or async* functions. |
| 1652 String completerName; | 1652 String completerName; |
| 1653 js.VariableUse get completer => new js.VariableUse(completerName); | 1653 js.VariableUse get completer => new js.VariableUse(completerName); |
| 1654 | 1654 |
| 1655 /// The function called by an async function to simulate an await or return. | 1655 /// The function called by an async function to initiate asynchronous |
| 1656 /// execution of the body. This is called with: |
| 1656 /// | 1657 /// |
| 1657 /// For an await it is called with: | 1658 /// - The body function [bodyName]. |
| 1659 /// - the completer object [completer]. |
| 1660 /// |
| 1661 /// It returns the completer's future. Passing the completer and returning its |
| 1662 /// future is a convenience to allow both the initiation and fetching the |
| 1663 /// future to be compactly encoded in a return statement's expression. |
| 1664 final js.Expression asyncStart; |
| 1665 |
| 1666 /// Function called by the async function to simulate an `await` |
| 1667 /// expression. It is called with: |
| 1658 /// | 1668 /// |
| 1659 /// - The value to await | 1669 /// - The value to await |
| 1660 /// - The body function [bodyName] | 1670 /// - The body function [bodyName] |
| 1671 final js.Expression asyncAwait; |
| 1672 |
| 1673 /// Function called by the async function to simulate a return. |
| 1674 /// It is called with: |
| 1675 /// |
| 1676 /// - The value to return |
| 1661 /// - The completer object [completer] | 1677 /// - The completer object [completer] |
| 1678 final js.Expression asyncReturn; |
| 1679 |
| 1680 /// Function called by the async function to simulate a rethrow. |
| 1681 /// It is called with: |
| 1662 /// | 1682 /// |
| 1663 /// For a return it is called with: | 1683 /// - The value containing the exception and stack |
| 1664 /// | |
| 1665 /// - The value to complete the completer with. | |
| 1666 /// - [error_codes.SUCCESS] | |
| 1667 /// - The completer object [completer] | 1684 /// - The completer object [completer] |
| 1668 /// | 1685 final js.Expression asyncRethrow; |
| 1669 /// For a throw it is called with: | |
| 1670 /// | |
| 1671 /// - The error to complete the completer with. | |
| 1672 /// - [error_codes.ERROR] | |
| 1673 /// - The completer object [completer] | |
| 1674 final js.Expression asyncHelper; | |
| 1675 | 1686 |
| 1676 /// Constructor used to initialize the [completer] variable. | 1687 /// Constructor used to initialize the [completer] variable. |
| 1677 /// | 1688 /// |
| 1678 /// Specific to async methods. | 1689 /// Specific to async methods. |
| 1679 final js.Expression completerFactory; | 1690 final js.Expression completerFactory; |
| 1680 | 1691 |
| 1681 final js.Expression wrapBody; | 1692 final js.Expression wrapBody; |
| 1682 | 1693 |
| 1683 AsyncRewriter(DiagnosticReporter reporter, Spannable spannable, | 1694 AsyncRewriter(DiagnosticReporter reporter, Spannable spannable, |
| 1684 {this.asyncHelper, | 1695 {this.asyncStart, |
| 1696 this.asyncAwait, |
| 1697 this.asyncReturn, |
| 1698 this.asyncRethrow, |
| 1685 this.completerFactory, | 1699 this.completerFactory, |
| 1686 this.wrapBody, | 1700 this.wrapBody, |
| 1687 String safeVariableName(String proposedName), | 1701 String safeVariableName(String proposedName), |
| 1688 js.Name bodyName}) | 1702 js.Name bodyName}) |
| 1689 : super(reporter, spannable, safeVariableName, bodyName); | 1703 : super(reporter, spannable, safeVariableName, bodyName); |
| 1690 | 1704 |
| 1691 @override | 1705 @override |
| 1692 void addYield(js.DartYield node, js.Expression expression) { | 1706 void addYield(js.DartYield node, js.Expression expression) { |
| 1693 reporter.internalError(spannable, "Yield in non-generating async function"); | 1707 reporter.internalError(spannable, "Yield in non-generating async function"); |
| 1694 } | 1708 } |
| 1695 | 1709 |
| 1696 void addErrorExit() { | 1710 void addErrorExit() { |
| 1697 beginLabel(rethrowLabel); | 1711 beginLabel(rethrowLabel); |
| 1698 addStatement(js.js.statement( | 1712 addStatement(js.js.statement( |
| 1699 "return #thenHelper(#currentError, #errorCode, #completer);", { | 1713 "return #thenHelper(#currentError, #completer);", { |
| 1700 "thenHelper": asyncHelper, | 1714 "thenHelper": asyncRethrow, |
| 1701 "errorCode": js.number(error_codes.ERROR), | |
| 1702 "currentError": currentError, | 1715 "currentError": currentError, |
| 1703 "completer": completer | 1716 "completer": completer |
| 1704 })); | 1717 })); |
| 1705 } | 1718 } |
| 1706 | 1719 |
| 1707 /// Returning from an async method calls [asyncStarHelper] with the result. | 1720 /// Returning from an async method calls [asyncStarHelper] with the result. |
| 1708 /// (the result might have been stored in [returnValue] by some finally | 1721 /// (the result might have been stored in [returnValue] by some finally |
| 1709 /// block). | 1722 /// block). |
| 1710 void addSuccesExit() { | 1723 void addSuccesExit() { |
| 1711 if (analysis.hasExplicitReturns) { | 1724 if (analysis.hasExplicitReturns) { |
| 1712 beginLabel(exitLabel); | 1725 beginLabel(exitLabel); |
| 1713 } else { | 1726 } else { |
| 1714 addStatement(new js.Comment("implicit return")); | 1727 addStatement(new js.Comment("implicit return")); |
| 1715 } | 1728 } |
| 1716 addStatement(js.js.statement( | 1729 addStatement( |
| 1717 "return #runtimeHelper(#returnValue, #successCode, #completer);", { | 1730 js.js.statement("return #runtimeHelper(#returnValue, #completer);", { |
| 1718 "runtimeHelper": asyncHelper, | 1731 "runtimeHelper": asyncReturn, |
| 1719 "successCode": js.number(error_codes.SUCCESS), | |
| 1720 "returnValue": | 1732 "returnValue": |
| 1721 analysis.hasExplicitReturns ? returnValue : new js.LiteralNull(), | 1733 analysis.hasExplicitReturns ? returnValue : new js.LiteralNull(), |
| 1722 "completer": completer | 1734 "completer": completer |
| 1723 })); | 1735 })); |
| 1724 } | 1736 } |
| 1725 | 1737 |
| 1726 @override | 1738 @override |
| 1727 Iterable<js.VariableInitialization> variableInitializations() { | 1739 Iterable<js.VariableInitialization> variableInitializations() { |
| 1728 List<js.VariableInitialization> variables = <js.VariableInitialization>[]; | 1740 List<js.VariableInitialization> variables = <js.VariableInitialization>[]; |
| 1729 variables.add( | 1741 variables.add( |
| 1730 _makeVariableInitializer(completer, new js.Call(completerFactory, []))); | 1742 _makeVariableInitializer(completer, new js.Call(completerFactory, []))); |
| 1731 if (analysis.hasExplicitReturns) { | 1743 if (analysis.hasExplicitReturns) { |
| 1732 variables.add(_makeVariableInitializer(returnValue, null)); | 1744 variables.add(_makeVariableInitializer(returnValue, null)); |
| 1733 } | 1745 } |
| 1734 return variables; | 1746 return variables; |
| 1735 } | 1747 } |
| 1736 | 1748 |
| 1737 @override | 1749 @override |
| 1738 void initializeNames() { | 1750 void initializeNames() { |
| 1739 completerName = freshName("completer"); | 1751 completerName = freshName("completer"); |
| 1740 } | 1752 } |
| 1741 | 1753 |
| 1742 @override | 1754 @override |
| 1743 js.Statement awaitStatement(js.Expression value) { | 1755 js.Statement awaitStatement(js.Expression value) { |
| 1744 return js.js.statement( | 1756 return js.js.statement( |
| 1745 """ | 1757 """ |
| 1746 return #asyncHelper(#value, | 1758 return #asyncHelper(#value, |
| 1747 #bodyName, | 1759 #bodyName); |
| 1748 #completer); | |
| 1749 """, | 1760 """, |
| 1750 { | 1761 { |
| 1751 "asyncHelper": asyncHelper, | 1762 "asyncHelper": asyncAwait, |
| 1752 "value": value, | 1763 "value": value, |
| 1753 "bodyName": bodyName, | 1764 "bodyName": bodyName, |
| 1754 "completer": completer | |
| 1755 }); | 1765 }); |
| 1756 } | 1766 } |
| 1757 | 1767 |
| 1758 @override | 1768 @override |
| 1759 js.Fun finishFunction( | 1769 js.Fun finishFunction( |
| 1760 List<js.Parameter> parameters, | 1770 List<js.Parameter> parameters, |
| 1761 js.Statement rewrittenBody, | 1771 js.Statement rewrittenBody, |
| 1762 js.VariableDeclarationList variableDeclarations, | 1772 js.VariableDeclarationList variableDeclarations, |
| 1763 SourceInformation sourceInformation) { | 1773 SourceInformation sourceInformation) { |
| 1764 return js.js( | 1774 return js.js( |
| 1765 """ | 1775 """ |
| 1766 function (#parameters) { | 1776 function (#parameters) { |
| 1767 #variableDeclarations; | 1777 #variableDeclarations; |
| 1768 var #bodyName = #wrapBody(function (#errorCode, #result) { | 1778 var #bodyName = #wrapBody(function (#errorCode, #result) { |
| 1769 if (#errorCode === #ERROR) { | 1779 if (#errorCode === #ERROR) { |
| 1770 #currentError = #result; | 1780 #currentError = #result; |
| 1771 #goto = #handler; | 1781 #goto = #handler; |
| 1772 } | 1782 } |
| 1773 #rewrittenBody; | 1783 #rewrittenBody; |
| 1774 }); | 1784 }); |
| 1775 return #asyncHelper(null, #bodyName, #completer); | 1785 return #asyncStart(#bodyName, #completer); |
| 1776 }""", | 1786 }""", |
| 1777 { | 1787 { |
| 1778 "parameters": parameters, | 1788 "parameters": parameters, |
| 1779 "variableDeclarations": variableDeclarations, | 1789 "variableDeclarations": variableDeclarations, |
| 1780 "ERROR": js.number(error_codes.ERROR), | 1790 "ERROR": js.number(error_codes.ERROR), |
| 1781 "rewrittenBody": rewrittenBody, | 1791 "rewrittenBody": rewrittenBody, |
| 1782 "bodyName": bodyName, | 1792 "bodyName": bodyName, |
| 1783 "currentError": currentError, | 1793 "currentError": currentError, |
| 1784 "goto": goto, | 1794 "goto": goto, |
| 1785 "handler": handler, | 1795 "handler": handler, |
| 1786 "errorCode": errorCodeName, | 1796 "errorCode": errorCodeName, |
| 1787 "result": resultName, | 1797 "result": resultName, |
| 1788 "asyncHelper": asyncHelper, | 1798 "asyncStart": asyncStart, |
| 1789 "completer": completer, | 1799 "completer": completer, |
| 1790 "wrapBody": wrapBody, | 1800 "wrapBody": wrapBody, |
| 1791 }).withSourceInformation(sourceInformation); | 1801 }).withSourceInformation(sourceInformation); |
| 1792 } | 1802 } |
| 1793 } | 1803 } |
| 1794 | 1804 |
| 1795 class SyncStarRewriter extends AsyncRewriterBase { | 1805 class SyncStarRewriter extends AsyncRewriterBase { |
| 1796 bool get isSyncStar => true; | 1806 bool get isSyncStar => true; |
| 1797 | 1807 |
| 1798 /// Constructor creating the Iterable for a sync* method. Called with | 1808 /// Constructor creating the Iterable for a sync* method. Called with |
| (...skipping 786 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2585 return condition || body; | 2595 return condition || body; |
| 2586 } | 2596 } |
| 2587 | 2597 |
| 2588 @override | 2598 @override |
| 2589 bool visitDartYield(js.DartYield node) { | 2599 bool visitDartYield(js.DartYield node) { |
| 2590 hasYield = true; | 2600 hasYield = true; |
| 2591 visit(node.expression); | 2601 visit(node.expression); |
| 2592 return true; | 2602 return true; |
| 2593 } | 2603 } |
| 2594 } | 2604 } |
| OLD | NEW |