| 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 1749 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1760 return variables; | 1760 return variables; |
| 1761 } | 1761 } |
| 1762 | 1762 |
| 1763 @override | 1763 @override |
| 1764 void initializeNames() { | 1764 void initializeNames() { |
| 1765 completerName = freshName("completer"); | 1765 completerName = freshName("completer"); |
| 1766 } | 1766 } |
| 1767 | 1767 |
| 1768 @override | 1768 @override |
| 1769 js.Statement awaitStatement(js.Expression value) { | 1769 js.Statement awaitStatement(js.Expression value) { |
| 1770 return js.js.statement( | 1770 return js.js.statement(""" |
| 1771 """ | |
| 1772 return #asyncHelper(#value, | 1771 return #asyncHelper(#value, |
| 1773 #bodyName); | 1772 #bodyName); |
| 1774 """, | 1773 """, { |
| 1775 { | 1774 "asyncHelper": asyncAwait, |
| 1776 "asyncHelper": asyncAwait, | 1775 "value": value, |
| 1777 "value": value, | 1776 "bodyName": bodyName, |
| 1778 "bodyName": bodyName, | 1777 }); |
| 1779 }); | |
| 1780 } | 1778 } |
| 1781 | 1779 |
| 1782 @override | 1780 @override |
| 1783 js.Fun finishFunction( | 1781 js.Fun finishFunction( |
| 1784 List<js.Parameter> parameters, | 1782 List<js.Parameter> parameters, |
| 1785 js.Statement rewrittenBody, | 1783 js.Statement rewrittenBody, |
| 1786 js.VariableDeclarationList variableDeclarations, | 1784 js.VariableDeclarationList variableDeclarations, |
| 1787 SourceInformation sourceInformation) { | 1785 SourceInformation sourceInformation) { |
| 1788 return js.js( | 1786 return js.js(""" |
| 1789 """ | |
| 1790 function (#parameters) { | 1787 function (#parameters) { |
| 1791 #variableDeclarations; | 1788 #variableDeclarations; |
| 1792 var #bodyName = #wrapBody(function (#errorCode, #result) { | 1789 var #bodyName = #wrapBody(function (#errorCode, #result) { |
| 1793 if (#errorCode === #ERROR) { | 1790 if (#errorCode === #ERROR) { |
| 1794 if (#hasHandlerLabels) { | 1791 if (#hasHandlerLabels) { |
| 1795 #currentError = #result; | 1792 #currentError = #result; |
| 1796 #goto = #handler; | 1793 #goto = #handler; |
| 1797 } else | 1794 } else |
| 1798 return #asyncRethrow(#result, #completer); | 1795 return #asyncRethrow(#result, #completer); |
| 1799 } | 1796 } |
| 1800 #rewrittenBody; | 1797 #rewrittenBody; |
| 1801 }); | 1798 }); |
| 1802 return #asyncStart(#bodyName, #completer); | 1799 return #asyncStart(#bodyName, #completer); |
| 1803 }""", | 1800 }""", { |
| 1804 { | 1801 "parameters": parameters, |
| 1805 "parameters": parameters, | 1802 "variableDeclarations": variableDeclarations, |
| 1806 "variableDeclarations": variableDeclarations, | 1803 "ERROR": js.number(error_codes.ERROR), |
| 1807 "ERROR": js.number(error_codes.ERROR), | 1804 "rewrittenBody": rewrittenBody, |
| 1808 "rewrittenBody": rewrittenBody, | 1805 "bodyName": bodyName, |
| 1809 "bodyName": bodyName, | 1806 "currentError": currentError, |
| 1810 "currentError": currentError, | 1807 "goto": goto, |
| 1811 "goto": goto, | 1808 "handler": handler, |
| 1812 "handler": handler, | 1809 "errorCode": errorCodeName, |
| 1813 "errorCode": errorCodeName, | 1810 "result": resultName, |
| 1814 "result": resultName, | 1811 "asyncStart": asyncStart, |
| 1815 "asyncStart": asyncStart, | 1812 "asyncRethrow": asyncRethrow, |
| 1816 "asyncRethrow": asyncRethrow, | 1813 "hasHandlerLabels": hasHandlerLabels, |
| 1817 "hasHandlerLabels": hasHandlerLabels, | 1814 "completer": completer, |
| 1818 "completer": completer, | 1815 "wrapBody": wrapBody, |
| 1819 "wrapBody": wrapBody, | 1816 }).withSourceInformation(sourceInformation); |
| 1820 }).withSourceInformation(sourceInformation); | |
| 1821 } | 1817 } |
| 1822 } | 1818 } |
| 1823 | 1819 |
| 1824 class SyncStarRewriter extends AsyncRewriterBase { | 1820 class SyncStarRewriter extends AsyncRewriterBase { |
| 1825 bool get isSyncStar => true; | 1821 bool get isSyncStar => true; |
| 1826 | 1822 |
| 1827 /// Constructor creating the Iterable for a sync* method. Called with | 1823 /// Constructor creating the Iterable for a sync* method. Called with |
| 1828 /// [bodyName]. | 1824 /// [bodyName]. |
| 1829 final js.Expression iterableFactory; | 1825 final js.Expression iterableFactory; |
| 1830 | 1826 |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1879 List<js.Parameter> renamedParameters = <js.Parameter>[]; | 1875 List<js.Parameter> renamedParameters = <js.Parameter>[]; |
| 1880 for (js.Parameter parameter in parameters) { | 1876 for (js.Parameter parameter in parameters) { |
| 1881 String name = parameter.name; | 1877 String name = parameter.name; |
| 1882 String renamedName = freshName(name); | 1878 String renamedName = freshName(name); |
| 1883 renamedParameters.add(new js.Parameter(renamedName)); | 1879 renamedParameters.add(new js.Parameter(renamedName)); |
| 1884 declarations.add(new js.VariableInitialization( | 1880 declarations.add(new js.VariableInitialization( |
| 1885 new js.VariableDeclaration(name), new js.VariableUse(renamedName))); | 1881 new js.VariableDeclaration(name), new js.VariableUse(renamedName))); |
| 1886 } | 1882 } |
| 1887 js.VariableDeclarationList copyParameters = | 1883 js.VariableDeclarationList copyParameters = |
| 1888 new js.VariableDeclarationList(declarations); | 1884 new js.VariableDeclarationList(declarations); |
| 1889 return js.js( | 1885 return js.js(""" |
| 1890 """ | |
| 1891 function (#renamedParameters) { | 1886 function (#renamedParameters) { |
| 1892 if (#needsThis) | 1887 if (#needsThis) |
| 1893 var #self = this; | 1888 var #self = this; |
| 1894 return #iterableFactory(function () { | 1889 return #iterableFactory(function () { |
| 1895 if (#hasParameters) { | 1890 if (#hasParameters) { |
| 1896 #copyParameters; | 1891 #copyParameters; |
| 1897 } | 1892 } |
| 1898 #varDecl; | 1893 #varDecl; |
| 1899 return function #body(#errorCode, #result) { | 1894 return function #body(#errorCode, #result) { |
| 1900 if (#errorCode === #ERROR) { | 1895 if (#errorCode === #ERROR) { |
| 1901 #currentError = #result; | 1896 #currentError = #result; |
| 1902 #goto = #handler; | 1897 #goto = #handler; |
| 1903 } | 1898 } |
| 1904 #helperBody; | 1899 #helperBody; |
| 1905 }; | 1900 }; |
| 1906 }); | 1901 }); |
| 1907 } | 1902 } |
| 1908 """, | 1903 """, { |
| 1909 { | 1904 "renamedParameters": renamedParameters, |
| 1910 "renamedParameters": renamedParameters, | 1905 "needsThis": analysis.hasThis, |
| 1911 "needsThis": analysis.hasThis, | 1906 "helperBody": rewrittenBody, |
| 1912 "helperBody": rewrittenBody, | 1907 "hasParameters": parameters.isNotEmpty, |
| 1913 "hasParameters": parameters.isNotEmpty, | 1908 "copyParameters": copyParameters, |
| 1914 "copyParameters": copyParameters, | 1909 "varDecl": variableDeclarations, |
| 1915 "varDecl": variableDeclarations, | 1910 "errorCode": errorCodeName, |
| 1916 "errorCode": errorCodeName, | 1911 "iterableFactory": iterableFactory, |
| 1917 "iterableFactory": iterableFactory, | 1912 "body": bodyName, |
| 1918 "body": bodyName, | 1913 "self": selfName, |
| 1919 "self": selfName, | 1914 "result": resultName, |
| 1920 "result": resultName, | 1915 "goto": goto, |
| 1921 "goto": goto, | 1916 "handler": handler, |
| 1922 "handler": handler, | 1917 "currentError": currentErrorName, |
| 1923 "currentError": currentErrorName, | 1918 "ERROR": js.number(error_codes.ERROR), |
| 1924 "ERROR": js.number(error_codes.ERROR), | 1919 }).withSourceInformation(sourceInformation); |
| 1925 }).withSourceInformation(sourceInformation); | |
| 1926 } | 1920 } |
| 1927 | 1921 |
| 1928 void addErrorExit() { | 1922 void addErrorExit() { |
| 1929 hasHandlerLabels = true; // TODO(sra): Add short form error handler. | 1923 hasHandlerLabels = true; // TODO(sra): Add short form error handler. |
| 1930 beginLabel(rethrowLabel); | 1924 beginLabel(rethrowLabel); |
| 1931 addStatement(js.js | 1925 addStatement(js.js |
| 1932 .statement('return #(#);', [uncaughtErrorExpression, currentError])); | 1926 .statement('return #(#);', [uncaughtErrorExpression, currentError])); |
| 1933 } | 1927 } |
| 1934 | 1928 |
| 1935 /// Returning from a sync* function returns an [endOfIteration] marker. | 1929 /// Returning from a sync* function returns an [endOfIteration] marker. |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2036 // canceled during the yield. | 2030 // canceled during the yield. |
| 2037 // At the bottom of the stack is the return label. | 2031 // At the bottom of the stack is the return label. |
| 2038 List<int> enclosingFinallyLabels = <int>[exitLabel]; | 2032 List<int> enclosingFinallyLabels = <int>[exitLabel]; |
| 2039 enclosingFinallyLabels.addAll(jumpTargets | 2033 enclosingFinallyLabels.addAll(jumpTargets |
| 2040 .where((js.Node node) => finallyLabels[node] != null) | 2034 .where((js.Node node) => finallyLabels[node] != null) |
| 2041 .map((js.Node node) => finallyLabels[node])); | 2035 .map((js.Node node) => finallyLabels[node])); |
| 2042 addStatement(js.js.statement("# = #;", [ | 2036 addStatement(js.js.statement("# = #;", [ |
| 2043 nextWhenCanceled, | 2037 nextWhenCanceled, |
| 2044 new js.ArrayInitializer(enclosingFinallyLabels.map(js.number).toList()) | 2038 new js.ArrayInitializer(enclosingFinallyLabels.map(js.number).toList()) |
| 2045 ])); | 2039 ])); |
| 2046 addStatement(js.js.statement( | 2040 addStatement(js.js.statement(""" |
| 2047 """ | |
| 2048 return #asyncStarHelper(#yieldExpression(#expression), #bodyName, | 2041 return #asyncStarHelper(#yieldExpression(#expression), #bodyName, |
| 2049 #controller);""", | 2042 #controller);""", { |
| 2050 { | 2043 "asyncStarHelper": asyncStarHelper, |
| 2051 "asyncStarHelper": asyncStarHelper, | 2044 "yieldExpression": node.hasStar ? yieldStarExpression : yieldExpression, |
| 2052 "yieldExpression": | 2045 "expression": expression, |
| 2053 node.hasStar ? yieldStarExpression : yieldExpression, | 2046 "bodyName": bodyName, |
| 2054 "expression": expression, | 2047 "controller": controllerName, |
| 2055 "bodyName": bodyName, | 2048 })); |
| 2056 "controller": controllerName, | |
| 2057 })); | |
| 2058 } | 2049 } |
| 2059 | 2050 |
| 2060 @override | 2051 @override |
| 2061 js.Fun finishFunction( | 2052 js.Fun finishFunction( |
| 2062 List<js.Parameter> parameters, | 2053 List<js.Parameter> parameters, |
| 2063 js.Statement rewrittenBody, | 2054 js.Statement rewrittenBody, |
| 2064 js.VariableDeclarationList variableDeclarations, | 2055 js.VariableDeclarationList variableDeclarations, |
| 2065 SourceInformation sourceInformation) { | 2056 SourceInformation sourceInformation) { |
| 2066 return js.js( | 2057 return js.js(""" |
| 2067 """ | |
| 2068 function (#parameters) { | 2058 function (#parameters) { |
| 2069 var #bodyName = #wrapBody(function (#errorCode, #result) { | 2059 var #bodyName = #wrapBody(function (#errorCode, #result) { |
| 2070 if (#hasYield) { | 2060 if (#hasYield) { |
| 2071 switch (#errorCode) { | 2061 switch (#errorCode) { |
| 2072 case #STREAM_WAS_CANCELED: | 2062 case #STREAM_WAS_CANCELED: |
| 2073 #next = #nextWhenCanceled; | 2063 #next = #nextWhenCanceled; |
| 2074 #goto = #next.pop(); | 2064 #goto = #next.pop(); |
| 2075 break; | 2065 break; |
| 2076 case #ERROR: | 2066 case #ERROR: |
| 2077 #currentError = #result; | 2067 #currentError = #result; |
| 2078 #goto = #handler; | 2068 #goto = #handler; |
| 2079 } | 2069 } |
| 2080 } else { | 2070 } else { |
| 2081 if (#errorCode === #ERROR) { | 2071 if (#errorCode === #ERROR) { |
| 2082 #currentError = #result; | 2072 #currentError = #result; |
| 2083 #goto = #handler; | 2073 #goto = #handler; |
| 2084 } | 2074 } |
| 2085 } | 2075 } |
| 2086 #rewrittenBody; | 2076 #rewrittenBody; |
| 2087 }); | 2077 }); |
| 2088 #variableDeclarations; | 2078 #variableDeclarations; |
| 2089 return #streamOfController(#controller); | 2079 return #streamOfController(#controller); |
| 2090 }""", | 2080 }""", { |
| 2091 { | 2081 "parameters": parameters, |
| 2092 "parameters": parameters, | 2082 "variableDeclarations": variableDeclarations, |
| 2093 "variableDeclarations": variableDeclarations, | 2083 "STREAM_WAS_CANCELED": js.number(error_codes.STREAM_WAS_CANCELED), |
| 2094 "STREAM_WAS_CANCELED": js.number(error_codes.STREAM_WAS_CANCELED), | 2084 "ERROR": js.number(error_codes.ERROR), |
| 2095 "ERROR": js.number(error_codes.ERROR), | 2085 "hasYield": analysis.hasYield, |
| 2096 "hasYield": analysis.hasYield, | 2086 "rewrittenBody": rewrittenBody, |
| 2097 "rewrittenBody": rewrittenBody, | 2087 "bodyName": bodyName, |
| 2098 "bodyName": bodyName, | 2088 "currentError": currentError, |
| 2099 "currentError": currentError, | 2089 "goto": goto, |
| 2100 "goto": goto, | 2090 "handler": handler, |
| 2101 "handler": handler, | 2091 "next": next, |
| 2102 "next": next, | 2092 "nextWhenCanceled": nextWhenCanceled, |
| 2103 "nextWhenCanceled": nextWhenCanceled, | 2093 "errorCode": errorCodeName, |
| 2104 "errorCode": errorCodeName, | 2094 "result": resultName, |
| 2105 "result": resultName, | 2095 "streamOfController": streamOfController, |
| 2106 "streamOfController": streamOfController, | 2096 "controller": controllerName, |
| 2107 "controller": controllerName, | 2097 "wrapBody": wrapBody, |
| 2108 "wrapBody": wrapBody, | 2098 }).withSourceInformation(sourceInformation); |
| 2109 }).withSourceInformation(sourceInformation); | |
| 2110 } | 2099 } |
| 2111 | 2100 |
| 2112 @override | 2101 @override |
| 2113 void addErrorExit() { | 2102 void addErrorExit() { |
| 2114 hasHandlerLabels = true; | 2103 hasHandlerLabels = true; |
| 2115 beginLabel(rethrowLabel); | 2104 beginLabel(rethrowLabel); |
| 2116 addStatement(js.js.statement( | 2105 addStatement(js.js.statement( |
| 2117 "return #asyncHelper(#currentError, #errorCode, #controller);", { | 2106 "return #asyncHelper(#currentError, #errorCode, #controller);", { |
| 2118 "asyncHelper": asyncStarHelper, | 2107 "asyncHelper": asyncStarHelper, |
| 2119 "errorCode": js.number(error_codes.ERROR), | 2108 "errorCode": js.number(error_codes.ERROR), |
| (...skipping 28 matching lines...) Expand all Loading... |
| 2148 } | 2137 } |
| 2149 | 2138 |
| 2150 @override | 2139 @override |
| 2151 void initializeNames() { | 2140 void initializeNames() { |
| 2152 controllerName = freshName("controller"); | 2141 controllerName = freshName("controller"); |
| 2153 nextWhenCanceledName = freshName("nextWhenCanceled"); | 2142 nextWhenCanceledName = freshName("nextWhenCanceled"); |
| 2154 } | 2143 } |
| 2155 | 2144 |
| 2156 @override | 2145 @override |
| 2157 js.Statement awaitStatement(js.Expression value) { | 2146 js.Statement awaitStatement(js.Expression value) { |
| 2158 return js.js.statement( | 2147 return js.js.statement(""" |
| 2159 """ | |
| 2160 return #asyncHelper(#value, | 2148 return #asyncHelper(#value, |
| 2161 #bodyName, | 2149 #bodyName, |
| 2162 #controller); | 2150 #controller); |
| 2163 """, | 2151 """, { |
| 2164 { | 2152 "asyncHelper": asyncStarHelper, |
| 2165 "asyncHelper": asyncStarHelper, | 2153 "value": value, |
| 2166 "value": value, | 2154 "bodyName": bodyName, |
| 2167 "bodyName": bodyName, | 2155 "controller": controllerName |
| 2168 "controller": controllerName | 2156 }); |
| 2169 }); | |
| 2170 } | 2157 } |
| 2171 } | 2158 } |
| 2172 | 2159 |
| 2173 /// Finds out | 2160 /// Finds out |
| 2174 /// | 2161 /// |
| 2175 /// - which expressions have yield or await nested in them. | 2162 /// - which expressions have yield or await nested in them. |
| 2176 /// - targets of jumps | 2163 /// - targets of jumps |
| 2177 /// - a set of used names. | 2164 /// - a set of used names. |
| 2178 /// - if any [This]-expressions are used. | 2165 /// - if any [This]-expressions are used. |
| 2179 class PreTranslationAnalysis extends js.NodeVisitor<bool> { | 2166 class PreTranslationAnalysis extends js.NodeVisitor<bool> { |
| (...skipping 436 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2616 return condition || body; | 2603 return condition || body; |
| 2617 } | 2604 } |
| 2618 | 2605 |
| 2619 @override | 2606 @override |
| 2620 bool visitDartYield(js.DartYield node) { | 2607 bool visitDartYield(js.DartYield node) { |
| 2621 hasYield = true; | 2608 hasYield = true; |
| 2622 visit(node.expression); | 2609 visit(node.expression); |
| 2623 return true; | 2610 return true; |
| 2624 } | 2611 } |
| 2625 } | 2612 } |
| OLD | NEW |