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 import 'dart:collection' show HashMap, HashSet; | 5 import 'dart:collection' show HashMap, HashSet; |
6 import 'dart:math' show min, max; | 6 import 'dart:math' show min, max; |
7 | 7 |
8 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; | 8 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; |
9 import 'package:analyzer/dart/ast/ast.dart'; | 9 import 'package:analyzer/dart/ast/ast.dart'; |
10 import 'package:analyzer/dart/ast/token.dart' show Token, TokenType; | 10 import 'package:analyzer/dart/ast/token.dart' show Token, TokenType; |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
109 FunctionBody _currentFunction; | 109 FunctionBody _currentFunction; |
110 | 110 |
111 /// Helper class for emitting elements in the proper order to allow | 111 /// Helper class for emitting elements in the proper order to allow |
112 /// JS to load the module. | 112 /// JS to load the module. |
113 ElementLoader _loader; | 113 ElementLoader _loader; |
114 | 114 |
115 BuildUnit _buildUnit; | 115 BuildUnit _buildUnit; |
116 | 116 |
117 String _buildRoot; | 117 String _buildRoot; |
118 | 118 |
119 /// Whether we are currently generating code for the body of a `JS()` call. | |
120 bool _isInForeignJS = false; | |
121 | |
119 CodeGenerator(AnalysisContext c, this.options, this._extensionTypes) | 122 CodeGenerator(AnalysisContext c, this.options, this._extensionTypes) |
120 : context = c, | 123 : context = c, |
121 types = c.typeProvider, | 124 types = c.typeProvider, |
122 _asyncStreamIterator = | 125 _asyncStreamIterator = |
123 _getLibrary(c, 'dart:async').getType('StreamIterator').type, | 126 _getLibrary(c, 'dart:async').getType('StreamIterator').type, |
124 _jsArray = _getLibrary(c, 'dart:_interceptors').getType('JSArray'), | 127 _jsArray = _getLibrary(c, 'dart:_interceptors').getType('JSArray'), |
125 dartCoreLibrary = _getLibrary(c, 'dart:core'), | 128 dartCoreLibrary = _getLibrary(c, 'dart:core'), |
126 dartJSLibrary = _getLibrary(c, 'dart:js'); | 129 dartJSLibrary = _getLibrary(c, 'dart:js'); |
127 | 130 |
128 LibraryElement get currentLibrary => _loader.currentElement.library; | 131 LibraryElement get currentLibrary => _loader.currentElement.library; |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
212 | 215 |
213 // Collect all Element -> Node mappings, in case we need to forward declare | 216 // Collect all Element -> Node mappings, in case we need to forward declare |
214 // any nodes. | 217 // any nodes. |
215 var nodes = new HashMap<Element, AstNode>.identity(); | 218 var nodes = new HashMap<Element, AstNode>.identity(); |
216 compilationUnits.map(_collectElements).forEach(nodes.addAll); | 219 compilationUnits.map(_collectElements).forEach(nodes.addAll); |
217 _loader = new ElementLoader(_emitModuleItem, nodes); | 220 _loader = new ElementLoader(_emitModuleItem, nodes); |
218 | 221 |
219 // Add implicit dart:core dependency so it is first. | 222 // Add implicit dart:core dependency so it is first. |
220 emitLibraryName(dartCoreLibrary); | 223 emitLibraryName(dartCoreLibrary); |
221 | 224 |
222 // | |
223 // Visit each compilation unit and emit its code. | 225 // Visit each compilation unit and emit its code. |
224 // | 226 // |
225 // NOTE: declarations are not necessarily emitted in this order. | 227 // NOTE: declarations are not necessarily emitted in this order. |
226 // Order will be changed as needed so the resulting code can execute. | 228 // Order will be changed as needed so the resulting code can execute. |
227 // This is done by forward declaring items. | 229 // This is done by forward declaring items. |
228 compilationUnits.forEach(visitCompilationUnit); | 230 compilationUnits.forEach(visitCompilationUnit); |
229 | 231 |
230 // Declare imports | 232 // Declare imports |
231 _finishImports(items); | 233 _finishImports(items); |
232 | 234 |
(...skipping 1769 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2002 | 2004 |
2003 // Get the original declaring element. If we had a property accessor, this | 2005 // Get the original declaring element. If we had a property accessor, this |
2004 // indirects back to a (possibly synthetic) field. | 2006 // indirects back to a (possibly synthetic) field. |
2005 var element = accessor; | 2007 var element = accessor; |
2006 if (accessor is PropertyAccessorElement) element = accessor.variable; | 2008 if (accessor is PropertyAccessorElement) element = accessor.variable; |
2007 | 2009 |
2008 _loader.declareBeforeUse(element); | 2010 _loader.declareBeforeUse(element); |
2009 | 2011 |
2010 // type literal | 2012 // type literal |
2011 if (element is TypeDefiningElement) { | 2013 if (element is TypeDefiningElement) { |
2012 return _emitTypeName(fillDynamicTypeArgs(element.type)); | 2014 var typeName = _emitTypeName(fillDynamicTypeArgs(element.type)); |
2015 | |
2016 // If the type is a type literal expression in Dart code, wrap the raw | |
2017 // runtime type in a "Type" instance. | |
2018 if (!_isInForeignJS && | |
2019 node.parent is! MethodInvocation && | |
2020 node.parent is! PrefixedIdentifier && | |
2021 node.parent is! PropertyAccess) { | |
2022 // A type literal expression in use. Wrap the runtime type in a "Type" o bject. | |
Jennifer Messerly
2016/05/03 20:59:54
long line.
Bob Nystrom
2016/05/03 21:24:32
Oops. Meant to delete that comment (I moved it out
| |
2023 typeName = js.call('dart.wrapType(#)', typeName); | |
2024 } | |
2025 | |
2026 return typeName; | |
2013 } | 2027 } |
2014 | 2028 |
2015 // library member | 2029 // library member |
2016 if (element.enclosingElement is CompilationUnitElement) { | 2030 if (element.enclosingElement is CompilationUnitElement) { |
2017 return _emitTopLevelName(element); | 2031 return _emitTopLevelName(element); |
2018 } | 2032 } |
2019 | 2033 |
2020 var name = element.name; | 2034 var name = element.name; |
2021 | 2035 |
2022 // Unqualified class member. This could mean implicit-this, or implicit | 2036 // Unqualified class member. This could mean implicit-this, or implicit |
(...skipping 447 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2470 return '#'; | 2484 return '#'; |
2471 } else { | 2485 } else { |
2472 return (element as InterpolationString).value; | 2486 return (element as InterpolationString).value; |
2473 } | 2487 } |
2474 }).join(); | 2488 }).join(); |
2475 } else { | 2489 } else { |
2476 templateArgs = args.skip(2); | 2490 templateArgs = args.skip(2); |
2477 source = (code as StringLiteral).stringValue; | 2491 source = (code as StringLiteral).stringValue; |
2478 } | 2492 } |
2479 | 2493 |
2480 var template = js.parseForeignJS(source); | 2494 // TODO(rnystrom): The JS() calls are almost never nested, and probably |
2481 var result = template.instantiate(_visitList(templateArgs)); | 2495 // really shouldn't be, but there are at least a couple of calls in the |
2482 // `throw` is emitted as a statement by `parseForeignJS`. | 2496 // HTML library where an argument to JS() is itself a JS() call. If those |
Jennifer Messerly
2016/05/03 20:59:54
haha, wow. The crazy stuff you find sometimes :)
Bob Nystrom
2016/05/03 21:24:32
Acknowledged.
| |
2483 assert(result is JS.Expression || node.parent is ExpressionStatement); | 2497 // go away, this can just assert(!_isInForeignJS). |
2484 return result; | 2498 var wasInForeignJS = _isInForeignJS; |
2499 try { | |
Jennifer Messerly
2016/05/03 20:59:54
nit: try/finally is not needed. We will never try
Bob Nystrom
2016/05/03 21:24:32
Done.
| |
2500 _isInForeignJS = true; | |
2501 | |
2502 var template = js.parseForeignJS(source); | |
2503 var result = template.instantiate(_visitList(templateArgs)); | |
2504 // `throw` is emitted as a statement by `parseForeignJS`. | |
2505 assert(result is JS.Expression || node.parent is ExpressionStatement); | |
2506 return result; | |
2507 } finally { | |
2508 _isInForeignJS = wasInForeignJS; | |
2509 } | |
2485 } | 2510 } |
2486 return null; | 2511 return null; |
2487 } | 2512 } |
2488 | 2513 |
2489 @override | 2514 @override |
2490 JS.Expression visitFunctionExpressionInvocation( | 2515 JS.Expression visitFunctionExpressionInvocation( |
2491 FunctionExpressionInvocation node) => | 2516 FunctionExpressionInvocation node) => |
2492 _emitFunctionCall(node); | 2517 _emitFunctionCall(node); |
2493 | 2518 |
2494 @override | 2519 @override |
(...skipping 1730 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4225 } | 4250 } |
4226 | 4251 |
4227 bool isLibraryPrefix(Expression node) => | 4252 bool isLibraryPrefix(Expression node) => |
4228 node is SimpleIdentifier && node.staticElement is PrefixElement; | 4253 node is SimpleIdentifier && node.staticElement is PrefixElement; |
4229 | 4254 |
4230 LibraryElement _getLibrary(AnalysisContext c, String uri) => | 4255 LibraryElement _getLibrary(AnalysisContext c, String uri) => |
4231 c.computeLibraryElement(c.sourceFactory.forUri(uri)); | 4256 c.computeLibraryElement(c.sourceFactory.forUri(uri)); |
4232 | 4257 |
4233 bool _isDartRuntime(LibraryElement l) => | 4258 bool _isDartRuntime(LibraryElement l) => |
4234 l.isInSdk && l.source.uri.toString() == 'dart:_runtime'; | 4259 l.isInSdk && l.source.uri.toString() == 'dart:_runtime'; |
OLD | NEW |