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 |