| 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:math" show max; | 7 import "dart:math" show max; |
| 8 import 'dart:collection'; | 8 import 'dart:collection'; |
| 9 | 9 |
| 10 import 'package:js_runtime/shared/async_await_error_codes.dart' | 10 import 'package:js_runtime/shared/async_await_error_codes.dart' |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 151 /// | 151 /// |
| 152 /// Used if there are untransformed loops containing break or continues to | 152 /// Used if there are untransformed loops containing break or continues to |
| 153 /// targets outside the loop. | 153 /// targets outside the loop. |
| 154 String outerLabelName; | 154 String outerLabelName; |
| 155 | 155 |
| 156 /// If javascript `this` is used, it is accessed via this variable, in the | 156 /// If javascript `this` is used, it is accessed via this variable, in the |
| 157 /// [bodyName] function. | 157 /// [bodyName] function. |
| 158 js.VariableUse get self => new js.VariableUse(selfName); | 158 js.VariableUse get self => new js.VariableUse(selfName); |
| 159 String selfName; | 159 String selfName; |
| 160 | 160 |
| 161 final DiagnosticListener diagnosticListener; | 161 final DiagnosticReporter reporter; |
| 162 // For error reporting only. | 162 // For error reporting only. |
| 163 Spannable get spannable { | 163 Spannable get spannable { |
| 164 return (_spannable == null) ? NO_LOCATION_SPANNABLE : _spannable; | 164 return (_spannable == null) ? NO_LOCATION_SPANNABLE : _spannable; |
| 165 } | 165 } |
| 166 | 166 |
| 167 Spannable _spannable; | 167 Spannable _spannable; |
| 168 | 168 |
| 169 int _currentLabel = 0; | 169 int _currentLabel = 0; |
| 170 | 170 |
| 171 // The highest temporary variable index currently in use. | 171 // The highest temporary variable index currently in use. |
| 172 int currentTempVarIndex = 0; | 172 int currentTempVarIndex = 0; |
| 173 // The highest temporary variable index ever in use in this function. | 173 // The highest temporary variable index ever in use in this function. |
| 174 int tempVarHighWaterMark = 0; | 174 int tempVarHighWaterMark = 0; |
| 175 Map<int, js.Expression> tempVarNames = new Map<int, js.Expression>(); | 175 Map<int, js.Expression> tempVarNames = new Map<int, js.Expression>(); |
| 176 | 176 |
| 177 bool get isAsync => false; | 177 bool get isAsync => false; |
| 178 bool get isSyncStar => false; | 178 bool get isSyncStar => false; |
| 179 bool get isAsyncStar => false; | 179 bool get isAsyncStar => false; |
| 180 | 180 |
| 181 AsyncRewriterBase(this.diagnosticListener, | 181 AsyncRewriterBase(this.reporter, |
| 182 spannable, | 182 this._spannable, |
| 183 this.safeVariableName, | 183 this.safeVariableName, |
| 184 this.bodyName) | 184 this.bodyName); |
| 185 : _spannable = spannable; | |
| 186 | 185 |
| 187 /// Initialize names used by the subClass. | 186 /// Initialize names used by the subClass. |
| 188 void initializeNames(); | 187 void initializeNames(); |
| 189 | 188 |
| 190 /// Main entry point. | 189 /// Main entry point. |
| 191 /// Rewrites a sync*/async/async* function to an equivalent normal function. | 190 /// Rewrites a sync*/async/async* function to an equivalent normal function. |
| 192 /// | 191 /// |
| 193 /// [spannable] can be passed to have a location for error messages. | 192 /// [spannable] can be passed to have a location for error messages. |
| 194 js.Fun rewrite(js.Fun node, [Spannable spannable]) { | 193 js.Fun rewrite(js.Fun node, [Spannable spannable]) { |
| 195 _spannable = spannable; | 194 _spannable = spannable; |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 345 bool shouldTransform(js.Node node) { | 344 bool shouldTransform(js.Node node) { |
| 346 return analysis.hasAwaitOrYield.contains(node); | 345 return analysis.hasAwaitOrYield.contains(node); |
| 347 } | 346 } |
| 348 | 347 |
| 349 void unsupported(js.Node node) { | 348 void unsupported(js.Node node) { |
| 350 throw new UnsupportedError( | 349 throw new UnsupportedError( |
| 351 "Node $node cannot be transformed by the await-sync transformer"); | 350 "Node $node cannot be transformed by the await-sync transformer"); |
| 352 } | 351 } |
| 353 | 352 |
| 354 void unreachable(js.Node node) { | 353 void unreachable(js.Node node) { |
| 355 diagnosticListener.internalError( | 354 reporter.internalError( |
| 356 spannable, "Internal error, trying to visit $node"); | 355 spannable, "Internal error, trying to visit $node"); |
| 357 } | 356 } |
| 358 | 357 |
| 359 visitStatement(js.Statement node) { | 358 visitStatement(js.Statement node) { |
| 360 node.accept(this); | 359 node.accept(this); |
| 361 } | 360 } |
| 362 | 361 |
| 363 /// Visits [node] to ensure its sideeffects are performed, but throwing away | 362 /// Visits [node] to ensure its sideeffects are performed, but throwing away |
| 364 /// the result. | 363 /// the result. |
| 365 /// | 364 /// |
| (...skipping 1003 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1369 for (js.SwitchClause clause in node.cases) { | 1368 for (js.SwitchClause clause in node.cases) { |
| 1370 if (clause is js.Case) { | 1369 if (clause is js.Case) { |
| 1371 labels[i] = newLabel("case"); | 1370 labels[i] = newLabel("case"); |
| 1372 clauses.add(new js.Case(visitExpression(clause.expression), | 1371 clauses.add(new js.Case(visitExpression(clause.expression), |
| 1373 gotoAndBreak(labels[i]))); | 1372 gotoAndBreak(labels[i]))); |
| 1374 } else if (clause is js.Default) { | 1373 } else if (clause is js.Default) { |
| 1375 labels[i] = newLabel("default"); | 1374 labels[i] = newLabel("default"); |
| 1376 clauses.add(new js.Default(gotoAndBreak(labels[i]))); | 1375 clauses.add(new js.Default(gotoAndBreak(labels[i]))); |
| 1377 hasDefault = true; | 1376 hasDefault = true; |
| 1378 } else { | 1377 } else { |
| 1379 diagnosticListener.internalError( | 1378 reporter.internalError( |
| 1380 spannable, "Unknown clause type $clause"); | 1379 spannable, "Unknown clause type $clause"); |
| 1381 } | 1380 } |
| 1382 i++; | 1381 i++; |
| 1383 } | 1382 } |
| 1384 if (!hasDefault) { | 1383 if (!hasDefault) { |
| 1385 clauses.add(new js.Default(gotoAndBreak(after))); | 1384 clauses.add(new js.Default(gotoAndBreak(after))); |
| 1386 } | 1385 } |
| 1387 withExpression(node.key, (js.Expression key) { | 1386 withExpression(node.key, (js.Expression key) { |
| 1388 addStatement(new js.Switch(key, clauses)); | 1387 addStatement(new js.Switch(key, clauses)); |
| 1389 }, store: false); | 1388 }, store: false); |
| (...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1688 /// - The completer object [completer] | 1687 /// - The completer object [completer] |
| 1689 final js.Expression asyncHelper; | 1688 final js.Expression asyncHelper; |
| 1690 | 1689 |
| 1691 /// Contructor used to initialize the [completer] variable. | 1690 /// Contructor used to initialize the [completer] variable. |
| 1692 /// | 1691 /// |
| 1693 /// Specific to async methods. | 1692 /// Specific to async methods. |
| 1694 final js.Expression newCompleter; | 1693 final js.Expression newCompleter; |
| 1695 | 1694 |
| 1696 final js.Expression wrapBody; | 1695 final js.Expression wrapBody; |
| 1697 | 1696 |
| 1698 AsyncRewriter(DiagnosticListener diagnosticListener, | 1697 AsyncRewriter(DiagnosticReporter reporter, |
| 1699 spannable, | 1698 Spannable spannable, |
| 1700 {this.asyncHelper, | 1699 {this.asyncHelper, |
| 1701 this.newCompleter, | 1700 this.newCompleter, |
| 1702 this.wrapBody, | 1701 this.wrapBody, |
| 1703 String safeVariableName(String proposedName), | 1702 String safeVariableName(String proposedName), |
| 1704 js.Name bodyName}) | 1703 js.Name bodyName}) |
| 1705 : super(diagnosticListener, | 1704 : super(reporter, |
| 1706 spannable, | 1705 spannable, |
| 1707 safeVariableName, | 1706 safeVariableName, |
| 1708 bodyName); | 1707 bodyName); |
| 1709 | 1708 |
| 1710 @override | 1709 @override |
| 1711 void addYield(js.DartYield node, js.Expression expression) { | 1710 void addYield(js.DartYield node, js.Expression expression) { |
| 1712 diagnosticListener.internalError(spannable, | 1711 reporter.internalError(spannable, |
| 1713 "Yield in non-generating async function"); | 1712 "Yield in non-generating async function"); |
| 1714 } | 1713 } |
| 1715 | 1714 |
| 1716 void addErrorExit() { | 1715 void addErrorExit() { |
| 1717 beginLabel(rethrowLabel); | 1716 beginLabel(rethrowLabel); |
| 1718 addStatement(js.js.statement( | 1717 addStatement(js.js.statement( |
| 1719 "return #thenHelper(#currentError, #errorCode, #completer);", { | 1718 "return #thenHelper(#currentError, #errorCode, #completer);", { |
| 1720 "thenHelper": asyncHelper, | 1719 "thenHelper": asyncHelper, |
| 1721 "errorCode": js.number(error_codes.ERROR), | 1720 "errorCode": js.number(error_codes.ERROR), |
| 1722 "currentError": currentError, | 1721 "currentError": currentError, |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1820 final js.Expression endOfIteration; | 1819 final js.Expression endOfIteration; |
| 1821 | 1820 |
| 1822 /// A JS Expression that creates a marker indication a 'yield*' statement. | 1821 /// A JS Expression that creates a marker indication a 'yield*' statement. |
| 1823 /// | 1822 /// |
| 1824 /// Called with the stream to yield from. | 1823 /// Called with the stream to yield from. |
| 1825 final js.Expression yieldStarExpression; | 1824 final js.Expression yieldStarExpression; |
| 1826 | 1825 |
| 1827 /// Used by sync* functions to throw exeptions. | 1826 /// Used by sync* functions to throw exeptions. |
| 1828 final js.Expression uncaughtErrorExpression; | 1827 final js.Expression uncaughtErrorExpression; |
| 1829 | 1828 |
| 1830 SyncStarRewriter(DiagnosticListener diagnosticListener, | 1829 SyncStarRewriter(DiagnosticReporter diagnosticListener, |
| 1831 spannable, | 1830 spannable, |
| 1832 {this.endOfIteration, | 1831 {this.endOfIteration, |
| 1833 this.newIterable, | 1832 this.newIterable, |
| 1834 this.yieldStarExpression, | 1833 this.yieldStarExpression, |
| 1835 this.uncaughtErrorExpression, | 1834 this.uncaughtErrorExpression, |
| 1836 String safeVariableName(String proposedName), | 1835 String safeVariableName(String proposedName), |
| 1837 js.Name bodyName}) | 1836 js.Name bodyName}) |
| 1838 : super(diagnosticListener, | 1837 : super(diagnosticListener, |
| 1839 spannable, | 1838 spannable, |
| 1840 safeVariableName, | 1839 safeVariableName, |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1930 | 1929 |
| 1931 @override | 1930 @override |
| 1932 Iterable<js.VariableInitialization> variableInitializations() { | 1931 Iterable<js.VariableInitialization> variableInitializations() { |
| 1933 List<js.VariableInitialization> variables = | 1932 List<js.VariableInitialization> variables = |
| 1934 new List<js.VariableInitialization>(); | 1933 new List<js.VariableInitialization>(); |
| 1935 return variables; | 1934 return variables; |
| 1936 } | 1935 } |
| 1937 | 1936 |
| 1938 @override | 1937 @override |
| 1939 js.Statement awaitStatement(js.Expression value) { | 1938 js.Statement awaitStatement(js.Expression value) { |
| 1940 throw diagnosticListener.internalError(spannable, | 1939 throw reporter.internalError(spannable, |
| 1941 "Sync* functions cannot contain await statements."); | 1940 "Sync* functions cannot contain await statements."); |
| 1942 } | 1941 } |
| 1943 | 1942 |
| 1944 @override | 1943 @override |
| 1945 void initializeNames() {} | 1944 void initializeNames() {} |
| 1946 } | 1945 } |
| 1947 | 1946 |
| 1948 class AsyncStarRewriter extends AsyncRewriterBase { | 1947 class AsyncStarRewriter extends AsyncRewriterBase { |
| 1949 | 1948 |
| 1950 bool get isAsyncStar => true; | 1949 bool get isAsyncStar => true; |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1991 /// Called with the value to yield. | 1990 /// Called with the value to yield. |
| 1992 final js.Expression yieldExpression; | 1991 final js.Expression yieldExpression; |
| 1993 | 1992 |
| 1994 /// A JS Expression that creates a marker indication a 'yield*' statement. | 1993 /// A JS Expression that creates a marker indication a 'yield*' statement. |
| 1995 /// | 1994 /// |
| 1996 /// Called with the stream to yield from. | 1995 /// Called with the stream to yield from. |
| 1997 final js.Expression yieldStarExpression; | 1996 final js.Expression yieldStarExpression; |
| 1998 | 1997 |
| 1999 final js.Expression wrapBody; | 1998 final js.Expression wrapBody; |
| 2000 | 1999 |
| 2001 AsyncStarRewriter(DiagnosticListener diagnosticListener, | 2000 AsyncStarRewriter(DiagnosticReporter reporter, |
| 2002 spannable, | 2001 Spannable spannable, |
| 2003 {this.asyncStarHelper, | 2002 {this.asyncStarHelper, |
| 2004 this.streamOfController, | 2003 this.streamOfController, |
| 2005 this.newController, | 2004 this.newController, |
| 2006 this.yieldExpression, | 2005 this.yieldExpression, |
| 2007 this.yieldStarExpression, | 2006 this.yieldStarExpression, |
| 2008 this.wrapBody, | 2007 this.wrapBody, |
| 2009 String safeVariableName(String proposedName), | 2008 String safeVariableName(String proposedName), |
| 2010 js.Name bodyName}) | 2009 js.Name bodyName}) |
| 2011 : super(diagnosticListener, | 2010 : super(reporter, |
| 2012 spannable, | 2011 spannable, |
| 2013 safeVariableName, | 2012 safeVariableName, |
| 2014 bodyName); | 2013 bodyName); |
| 2015 | 2014 |
| 2016 | 2015 |
| 2017 /// Translates a yield/yield* in an async* function. | 2016 /// Translates a yield/yield* in an async* function. |
| 2018 /// | 2017 /// |
| 2019 /// yield/yield* in an async* function is translated much like the `await` is | 2018 /// yield/yield* in an async* function is translated much like the `await` is |
| 2020 /// translated in [visitAwait], only the object is wrapped in a | 2019 /// translated in [visitAwait], only the object is wrapped in a |
| 2021 /// [yieldExpression]/[yieldStarExpression] to let [asyncStarHelper] | 2020 /// [yieldExpression]/[yieldStarExpression] to let [asyncStarHelper] |
| (...skipping 575 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2597 return condition || body; | 2596 return condition || body; |
| 2598 } | 2597 } |
| 2599 | 2598 |
| 2600 @override | 2599 @override |
| 2601 bool visitDartYield(js.DartYield node) { | 2600 bool visitDartYield(js.DartYield node) { |
| 2602 hasYield = true; | 2601 hasYield = true; |
| 2603 visit(node.expression); | 2602 visit(node.expression); |
| 2604 return true; | 2603 return true; |
| 2605 } | 2604 } |
| 2606 } | 2605 } |
| OLD | NEW |