Chromium Code Reviews| Index: lib/src/compiler/code_generator.dart |
| diff --git a/lib/src/compiler/code_generator.dart b/lib/src/compiler/code_generator.dart |
| index 1276c85eaeaeed3e9b6f4a7bbe8d4cff67e002fc..753a7d464f297b54006304ed7a75b992447c0639 100644 |
| --- a/lib/src/compiler/code_generator.dart |
| +++ b/lib/src/compiler/code_generator.dart |
| @@ -116,6 +116,10 @@ class CodeGenerator extends GeneralizingAstVisitor |
| String _buildRoot; |
| + bool _superAllowed = true; |
| + |
| + List<JS.Method> _superHelpers = <JS.Method>[]; |
| + |
| CodeGenerator(AnalysisContext c, this.options, this._extensionTypes) |
| : context = c, |
| types = c.typeProvider, |
| @@ -832,7 +836,7 @@ class CodeGenerator extends GeneralizingAstVisitor |
| jsMethods |
| .add(_emitConstructor(m, type, fields, virtualFields, isObject)); |
| } else if (m is MethodDeclaration) { |
| - jsMethods.add(_emitMethodDeclaration(type, m)); |
| + jsMethods.add(_emitMethodDeclaration(m)); |
| if (m.element is PropertyAccessorElement) { |
| jsMethods.add(_emitSuperAccessorWrapper(m, type, superclasses)); |
| @@ -868,6 +872,10 @@ class CodeGenerator extends GeneralizingAstVisitor |
| jsMethods.add(_emitIterable(type)); |
| } |
| + // Add all of the super helper methods |
| + jsMethods.addAll(_superHelpers); |
| + _superHelpers.clear(); |
| + |
| return jsMethods.where((m) => m != null).toList(growable: false); |
| } |
| @@ -1616,7 +1624,7 @@ class CodeGenerator extends GeneralizingAstVisitor |
| } |
| } |
| - JS.Method _emitMethodDeclaration(DartType type, MethodDeclaration node) { |
| + JS.Method _emitMethodDeclaration(MethodDeclaration node) { |
| if (node.isAbstract) { |
| return null; |
| } |
| @@ -1939,8 +1947,11 @@ class CodeGenerator extends GeneralizingAstVisitor |
| } else { |
| _asyncStarController = null; |
| } |
| + var savedSuperAllowed = _superAllowed; |
| + _superAllowed = false; |
| // Visit the body with our async* controller set. |
| var jsBody = _visit(body); |
| + _superAllowed = savedSuperAllowed; |
| _asyncStarController = savedController; |
| DartType returnType = _getExpectedReturnType(element); |
| @@ -2359,6 +2370,11 @@ class CodeGenerator extends GeneralizingAstVisitor |
| } |
| jsTarget = new JS.PropertyAccess(jsTarget, memberName); |
| + |
| + if (target is SuperExpression && !_superAllowed) { |
| + return _emitSuperForwarder(node, jsTarget, typeArgs, args); |
| + } |
| + |
| if (typeArgs != null) jsTarget = new JS.Call(jsTarget, typeArgs); |
| if (DynamicInvoke.get(node.methodName)) { |
|
Jennifer Messerly
2016/05/03 18:56:18
Is there a way to restructure this code so it's re
Harry Terkelsen
2016/05/05 23:37:35
There is a way ;)
|
| @@ -2371,6 +2387,56 @@ class CodeGenerator extends GeneralizingAstVisitor |
| return new JS.Call(jsTarget, args); |
| } |
| + JS.Expression _emitSuperForwarder( |
| + MethodInvocation node, |
| + JS.PropertyAccess jsTarget, |
| + List<JS.Expression> typeArgs, |
| + List<JS.Expression> args) { |
| + var helperMethod = _getSuperHelperFor(node, jsTarget, typeArgs, args); |
| + var newTarget = new JS.PropertyAccess(new JS.This(), helperMethod); |
| + var helperArgs = <JS.Expression>[]; |
| + if (typeArgs != null) { |
| + helperArgs.addAll(typeArgs); |
| + } |
| + helperArgs.addAll(args); |
| + return new JS.Call(newTarget, helperArgs); |
|
Jennifer Messerly
2016/05/03 18:56:18
FYI: you could build these like:
return js.call('
Harry Terkelsen
2016/05/05 23:37:34
Done.
|
| + } |
| + |
| + JS.Expression _getSuperHelperFor( |
|
Jennifer Messerly
2016/05/03 18:56:18
Probably worth a doc comment about what this metho
|
| + MethodInvocation node, |
| + JS.PropertyAccess jsTarget, |
| + List<JS.Expression> typeArgs, |
|
Jennifer Messerly
2016/05/03 18:56:18
Hmmm, this is an interesting approach. It's one su
|
| + List<JS.Expression> args) { |
| + var counter = 0; |
| + var helperArgs = |
| + new List.generate(typeArgs?.length ?? 0 + args.length, (index) { |
| + new JS.Identifier('a${counter++}'); |
|
Jennifer Messerly
2016/05/03 18:56:18
this should be symbolized so it doesn't collide wi
Harry Terkelsen
2016/05/05 23:37:34
Done.
|
| + }, growable: false); |
| + |
| + var newTarget; |
| + if (typeArgs != null) { |
| + newTarget = new JS.Call(jsTarget, helperArgs.sublist(0, typeArgs.length)); |
| + } else { |
| + newTarget = jsTarget; |
| + } |
| + |
| + var forwardedCall; |
| + if (DynamicInvoke.get(node.methodName)) { |
| + forwardedCall = js.call('dart.dcall(#, #)', |
| + [newTarget, helperArgs.sublist(typeArgs?.length ?? 0)]); |
| + } else { |
| + forwardedCall = |
| + new JS.Call(newTarget, helperArgs.sublist(typeArgs?.length ?? 0)); |
| + } |
| + |
| + var helperMethod = |
| + new JS.Fun(helperArgs, new JS.Block([new JS.Return(forwardedCall)])); |
| + var helperMethodName = |
| + js.string('super\$${node.methodName.name}${_superHelpers.length}', "'"); |
|
Jennifer Messerly
2016/05/03 18:56:18
based on comment above, "helperMethodName" will ju
Harry Terkelsen
2016/05/05 23:37:34
Done.
|
| + _superHelpers.add(new JS.Method(helperMethodName, helperMethod)); |
| + return helperMethodName; |
| + } |
| + |
| /// Emits a function call, to a top-level function, local function, or |
| /// an expression. |
| JS.Expression _emitFunctionCall(InvocationExpression node) { |
| @@ -3723,8 +3789,12 @@ class CodeGenerator extends GeneralizingAstVisitor |
| @override |
| visitTryStatement(TryStatement node) { |
| - return new JS.Try(_visit(node.body), _visitCatch(node.catchClauses), |
| - _visit(node.finallyBlock)); |
| + var savedSuperAllowed = _superAllowed; |
| + _superAllowed = false; |
| + var finallyBlock = _visit(node.finallyBlock); |
| + _superAllowed = savedSuperAllowed; |
| + return new JS.Try( |
| + _visit(node.body), _visitCatch(node.catchClauses), finallyBlock); |
| } |
| _visitCatch(NodeList<CatchClause> clauses) { |