Chromium Code Reviews| 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 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 120 /// | 120 /// |
| 121 /// To "goto" a label, the label is assigned to this variable, and break out | 121 /// To "goto" a label, the label is assigned to this variable, and break out |
| 122 /// of the switch to take another iteration in the while loop. See [addGoto] | 122 /// of the switch to take another iteration in the while loop. See [addGoto] |
| 123 js.VariableUse get goto => new js.VariableUse(gotoName); | 123 js.VariableUse get goto => new js.VariableUse(gotoName); |
| 124 String gotoName; | 124 String gotoName; |
| 125 | 125 |
| 126 /// Variable containing the label of the current error handler. | 126 /// Variable containing the label of the current error handler. |
| 127 js.VariableUse get handler => new js.VariableUse(handlerName); | 127 js.VariableUse get handler => new js.VariableUse(handlerName); |
| 128 String handlerName; | 128 String handlerName; |
| 129 | 129 |
| 130 /// Set to `true` if any of the switch statement labels is a handler. | |
| 131 bool hasHandlerLabels = false; | |
| 132 | |
| 130 /// A stack of labels of finally blocks to visit, and the label to go to after | 133 /// A stack of labels of finally blocks to visit, and the label to go to after |
| 131 /// the last. | 134 /// the last. |
| 132 js.VariableUse get next => new js.VariableUse(nextName); | 135 js.VariableUse get next => new js.VariableUse(nextName); |
| 133 String nextName; | 136 String nextName; |
| 134 | 137 |
| 135 /// The current returned value (a finally block may overwrite it). | 138 /// The current returned value (a finally block may overwrite it). |
| 136 js.VariableUse get returnValue => new js.VariableUse(returnValueName); | 139 js.VariableUse get returnValue => new js.VariableUse(returnValueName); |
| 137 String returnValueName; | 140 String returnValueName; |
| 138 | 141 |
| 139 /// Stores the current error when we are in the process of handling an error. | 142 /// Stores the current error when we are in the process of handling an error. |
| (...skipping 538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 678 }).toList(); | 681 }).toList(); |
| 679 js.Statement rewrittenBody = new js.Switch(goto, clauses); | 682 js.Statement rewrittenBody = new js.Switch(goto, clauses); |
| 680 if (hasJumpThoughOuterLabel) { | 683 if (hasJumpThoughOuterLabel) { |
| 681 rewrittenBody = new js.LabeledStatement(outerLabelName, rewrittenBody); | 684 rewrittenBody = new js.LabeledStatement(outerLabelName, rewrittenBody); |
| 682 } | 685 } |
| 683 rewrittenBody = js.js.statement('while (true) {#}', rewrittenBody); | 686 rewrittenBody = js.js.statement('while (true) {#}', rewrittenBody); |
| 684 List<js.VariableInitialization> variables = <js.VariableInitialization>[]; | 687 List<js.VariableInitialization> variables = <js.VariableInitialization>[]; |
| 685 | 688 |
| 686 variables.add(_makeVariableInitializer(goto, js.number(0))); | 689 variables.add(_makeVariableInitializer(goto, js.number(0))); |
| 687 variables.addAll(variableInitializations()); | 690 variables.addAll(variableInitializations()); |
| 688 variables.add(_makeVariableInitializer(handler, js.number(rethrowLabel))); | 691 if (hasHandlerLabels) { |
| 689 variables.add(_makeVariableInitializer(currentError, null)); | 692 variables.add(_makeVariableInitializer(handler, js.number(rethrowLabel))); |
| 693 variables.add(_makeVariableInitializer(currentError, null)); | |
| 694 } | |
| 690 if (analysis.hasFinally || (isAsyncStar && analysis.hasYield)) { | 695 if (analysis.hasFinally || (isAsyncStar && analysis.hasYield)) { |
| 691 variables.add(_makeVariableInitializer( | 696 variables.add(_makeVariableInitializer( |
| 692 next, new js.ArrayInitializer(<js.Expression>[]))); | 697 next, new js.ArrayInitializer(<js.Expression>[]))); |
| 693 } | 698 } |
| 694 if (analysis.hasThis && !isSyncStar) { | 699 if (analysis.hasThis && !isSyncStar) { |
| 695 // Sync* functions must remember `this` on the level of the outer | 700 // Sync* functions must remember `this` on the level of the outer |
| 696 // function. | 701 // function. |
| 697 variables.add(_makeVariableInitializer(self, js.js('this'))); | 702 variables.add(_makeVariableInitializer(self, js.js('this'))); |
| 698 } | 703 } |
| 699 variables.addAll(localVariables.map((js.VariableDeclaration declaration) { | 704 variables.addAll(localVariables.map((js.VariableDeclaration declaration) { |
| (...skipping 705 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1405 | 1410 |
| 1406 @override | 1411 @override |
| 1407 void visitThrow(js.Throw node) { | 1412 void visitThrow(js.Throw node) { |
| 1408 withExpression(node.expression, (js.Expression expression) { | 1413 withExpression(node.expression, (js.Expression expression) { |
| 1409 addStatement(new js.Throw(expression) | 1414 addStatement(new js.Throw(expression) |
| 1410 .withSourceInformation(node.sourceInformation)); | 1415 .withSourceInformation(node.sourceInformation)); |
| 1411 }, store: false); | 1416 }, store: false); |
| 1412 } | 1417 } |
| 1413 | 1418 |
| 1414 setErrorHandler([int errorHandler]) { | 1419 setErrorHandler([int errorHandler]) { |
| 1420 hasHandlerLabels = true; | |
| 1415 js.Expression label = | 1421 js.Expression label = |
| 1416 (errorHandler == null) ? currentErrorHandler : js.number(errorHandler); | 1422 (errorHandler == null) ? currentErrorHandler : js.number(errorHandler); |
| 1417 addStatement(js.js.statement('# = #;', [handler, label])); | 1423 addStatement(js.js.statement('# = #;', [handler, label])); |
| 1418 } | 1424 } |
| 1419 | 1425 |
| 1420 List<int> _finalliesUpToAndEnclosingHandler() { | 1426 List<int> _finalliesUpToAndEnclosingHandler() { |
| 1421 List<int> result = <int>[]; | 1427 List<int> result = <int>[]; |
| 1422 for (int i = jumpTargets.length - 1; i >= 0; i--) { | 1428 for (int i = jumpTargets.length - 1; i >= 0; i--) { |
| 1423 js.Node node = jumpTargets[i]; | 1429 js.Node node = jumpTargets[i]; |
| 1424 int handlerLabel = handlerLabels[node]; | 1430 int handlerLabel = handlerLabels[node]; |
| (...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1701 String safeVariableName(String proposedName), | 1707 String safeVariableName(String proposedName), |
| 1702 js.Name bodyName}) | 1708 js.Name bodyName}) |
| 1703 : super(reporter, spannable, safeVariableName, bodyName); | 1709 : super(reporter, spannable, safeVariableName, bodyName); |
| 1704 | 1710 |
| 1705 @override | 1711 @override |
| 1706 void addYield(js.DartYield node, js.Expression expression) { | 1712 void addYield(js.DartYield node, js.Expression expression) { |
| 1707 reporter.internalError(spannable, "Yield in non-generating async function"); | 1713 reporter.internalError(spannable, "Yield in non-generating async function"); |
| 1708 } | 1714 } |
| 1709 | 1715 |
| 1710 void addErrorExit() { | 1716 void addErrorExit() { |
| 1717 if (!hasHandlerLabels) return; | |
| 1711 beginLabel(rethrowLabel); | 1718 beginLabel(rethrowLabel); |
| 1712 addStatement(js.js.statement( | 1719 addStatement(js.js.statement( |
| 1713 "return #thenHelper(#currentError, #completer);", { | 1720 "return #thenHelper(#currentError, #completer);", { |
| 1714 "thenHelper": asyncRethrow, | 1721 "thenHelper": asyncRethrow, |
| 1715 "currentError": currentError, | 1722 "currentError": currentError, |
| 1716 "completer": completer | 1723 "completer": completer |
| 1717 })); | 1724 })); |
| 1718 } | 1725 } |
| 1719 | 1726 |
| 1720 /// Returning from an async method calls [asyncStarHelper] with the result. | 1727 /// Returning from an async method calls [asyncStarHelper] with the result. |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1770 List<js.Parameter> parameters, | 1777 List<js.Parameter> parameters, |
| 1771 js.Statement rewrittenBody, | 1778 js.Statement rewrittenBody, |
| 1772 js.VariableDeclarationList variableDeclarations, | 1779 js.VariableDeclarationList variableDeclarations, |
| 1773 SourceInformation sourceInformation) { | 1780 SourceInformation sourceInformation) { |
| 1774 return js.js( | 1781 return js.js( |
| 1775 """ | 1782 """ |
| 1776 function (#parameters) { | 1783 function (#parameters) { |
| 1777 #variableDeclarations; | 1784 #variableDeclarations; |
| 1778 var #bodyName = #wrapBody(function (#errorCode, #result) { | 1785 var #bodyName = #wrapBody(function (#errorCode, #result) { |
| 1779 if (#errorCode === #ERROR) { | 1786 if (#errorCode === #ERROR) { |
| 1780 #currentError = #result; | 1787 if (#hasHandlerLabels) { |
| 1781 #goto = #handler; | 1788 #currentError = #result; |
| 1789 #goto = #handler; | |
| 1790 } else | |
| 1791 return #asyncRethrow(#result, #completer); | |
| 1782 } | 1792 } |
| 1783 #rewrittenBody; | 1793 #rewrittenBody; |
| 1784 }); | 1794 }); |
| 1785 return #asyncStart(#bodyName, #completer); | 1795 return #asyncStart(#bodyName, #completer); |
| 1786 }""", | 1796 }""", |
| 1787 { | 1797 { |
| 1788 "parameters": parameters, | 1798 "parameters": parameters, |
| 1789 "variableDeclarations": variableDeclarations, | 1799 "variableDeclarations": variableDeclarations, |
| 1790 "ERROR": js.number(error_codes.ERROR), | 1800 "ERROR": js.number(error_codes.ERROR), |
| 1791 "rewrittenBody": rewrittenBody, | 1801 "rewrittenBody": rewrittenBody, |
| 1792 "bodyName": bodyName, | 1802 "bodyName": bodyName, |
| 1793 "currentError": currentError, | 1803 "currentError": currentError, |
| 1794 "goto": goto, | 1804 "goto": goto, |
| 1795 "handler": handler, | 1805 "handler": handler, |
| 1796 "errorCode": errorCodeName, | 1806 "errorCode": errorCodeName, |
| 1797 "result": resultName, | 1807 "result": resultName, |
| 1798 "asyncStart": asyncStart, | 1808 "asyncStart": asyncStart, |
| 1809 "asyncRethrow": asyncRethrow, | |
| 1810 "hasHandlerLabels": hasHandlerLabels, | |
| 1799 "completer": completer, | 1811 "completer": completer, |
| 1800 "wrapBody": wrapBody, | 1812 "wrapBody": wrapBody, |
| 1801 }).withSourceInformation(sourceInformation); | 1813 }).withSourceInformation(sourceInformation); |
| 1802 } | 1814 } |
| 1803 } | 1815 } |
| 1804 | 1816 |
| 1805 class SyncStarRewriter extends AsyncRewriterBase { | 1817 class SyncStarRewriter extends AsyncRewriterBase { |
| 1806 bool get isSyncStar => true; | 1818 bool get isSyncStar => true; |
| 1807 | 1819 |
| 1808 /// Constructor creating the Iterable for a sync* method. Called with | 1820 /// Constructor creating the Iterable for a sync* method. Called with |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1900 "self": selfName, | 1912 "self": selfName, |
| 1901 "result": resultName, | 1913 "result": resultName, |
| 1902 "goto": goto, | 1914 "goto": goto, |
| 1903 "handler": handler, | 1915 "handler": handler, |
| 1904 "currentError": currentErrorName, | 1916 "currentError": currentErrorName, |
| 1905 "ERROR": js.number(error_codes.ERROR), | 1917 "ERROR": js.number(error_codes.ERROR), |
| 1906 }).withSourceInformation(sourceInformation); | 1918 }).withSourceInformation(sourceInformation); |
| 1907 } | 1919 } |
| 1908 | 1920 |
| 1909 void addErrorExit() { | 1921 void addErrorExit() { |
| 1922 hasHandlerLabels = true; | |
|
floitsch
2017/05/04 08:52:05
This is too confusing, but I'm guessing this is ju
sra1
2017/05/05 21:52:34
I added a field comment and a TODO comment here to
| |
| 1910 beginLabel(rethrowLabel); | 1923 beginLabel(rethrowLabel); |
| 1911 addStatement(js.js | 1924 addStatement(js.js |
| 1912 .statement('return #(#);', [uncaughtErrorExpression, currentError])); | 1925 .statement('return #(#);', [uncaughtErrorExpression, currentError])); |
| 1913 } | 1926 } |
| 1914 | 1927 |
| 1915 /// Returning from a sync* function returns an [endOfIteration] marker. | 1928 /// Returning from a sync* function returns an [endOfIteration] marker. |
| 1916 void addSuccesExit() { | 1929 void addSuccesExit() { |
| 1917 if (analysis.hasExplicitReturns) { | 1930 if (analysis.hasExplicitReturns) { |
| 1918 beginLabel(exitLabel); | 1931 beginLabel(exitLabel); |
| 1919 } else { | 1932 } else { |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2084 "errorCode": errorCodeName, | 2097 "errorCode": errorCodeName, |
| 2085 "result": resultName, | 2098 "result": resultName, |
| 2086 "streamOfController": streamOfController, | 2099 "streamOfController": streamOfController, |
| 2087 "controller": controllerName, | 2100 "controller": controllerName, |
| 2088 "wrapBody": wrapBody, | 2101 "wrapBody": wrapBody, |
| 2089 }).withSourceInformation(sourceInformation); | 2102 }).withSourceInformation(sourceInformation); |
| 2090 } | 2103 } |
| 2091 | 2104 |
| 2092 @override | 2105 @override |
| 2093 void addErrorExit() { | 2106 void addErrorExit() { |
| 2107 hasHandlerLabels = true; | |
|
floitsch
2017/05/04 08:52:05
ditto.
| |
| 2094 beginLabel(rethrowLabel); | 2108 beginLabel(rethrowLabel); |
| 2095 addStatement(js.js.statement( | 2109 addStatement(js.js.statement( |
| 2096 "return #asyncHelper(#currentError, #errorCode, #controller);", { | 2110 "return #asyncHelper(#currentError, #errorCode, #controller);", { |
| 2097 "asyncHelper": asyncStarHelper, | 2111 "asyncHelper": asyncStarHelper, |
| 2098 "errorCode": js.number(error_codes.ERROR), | 2112 "errorCode": js.number(error_codes.ERROR), |
| 2099 "currentError": currentError, | 2113 "currentError": currentError, |
| 2100 "controller": controllerName | 2114 "controller": controllerName |
| 2101 })); | 2115 })); |
| 2102 } | 2116 } |
| 2103 | 2117 |
| (...skipping 491 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2595 return condition || body; | 2609 return condition || body; |
| 2596 } | 2610 } |
| 2597 | 2611 |
| 2598 @override | 2612 @override |
| 2599 bool visitDartYield(js.DartYield node) { | 2613 bool visitDartYield(js.DartYield node) { |
| 2600 hasYield = true; | 2614 hasYield = true; |
| 2601 visit(node.expression); | 2615 visit(node.expression); |
| 2602 return true; | 2616 return true; |
| 2603 } | 2617 } |
| 2604 } | 2618 } |
| OLD | NEW |