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 typeName = js.call('dart.wrapType(#)', typeName); |
| 2023 } |
| 2024 |
| 2025 return typeName; |
2013 } | 2026 } |
2014 | 2027 |
2015 // library member | 2028 // library member |
2016 if (element.enclosingElement is CompilationUnitElement) { | 2029 if (element.enclosingElement is CompilationUnitElement) { |
2017 return _emitTopLevelName(element); | 2030 return _emitTopLevelName(element); |
2018 } | 2031 } |
2019 | 2032 |
2020 var name = element.name; | 2033 var name = element.name; |
2021 | 2034 |
2022 // Unqualified class member. This could mean implicit-this, or implicit | 2035 // 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 '#'; | 2483 return '#'; |
2471 } else { | 2484 } else { |
2472 return (element as InterpolationString).value; | 2485 return (element as InterpolationString).value; |
2473 } | 2486 } |
2474 }).join(); | 2487 }).join(); |
2475 } else { | 2488 } else { |
2476 templateArgs = args.skip(2); | 2489 templateArgs = args.skip(2); |
2477 source = (code as StringLiteral).stringValue; | 2490 source = (code as StringLiteral).stringValue; |
2478 } | 2491 } |
2479 | 2492 |
| 2493 // TODO(rnystrom): The JS() calls are almost never nested, and probably |
| 2494 // really shouldn't be, but there are at least a couple of calls in the |
| 2495 // HTML library where an argument to JS() is itself a JS() call. If those |
| 2496 // go away, this can just assert(!_isInForeignJS). |
| 2497 // Inside JS(), type names evaluate to the raw runtime type, not the |
| 2498 // wrapped Type object. |
| 2499 var wasInForeignJS = _isInForeignJS; |
| 2500 _isInForeignJS = true; |
| 2501 |
2480 var template = js.parseForeignJS(source); | 2502 var template = js.parseForeignJS(source); |
2481 var result = template.instantiate(_visitList(templateArgs)); | 2503 var result = template.instantiate(_visitList(templateArgs)); |
| 2504 |
| 2505 _isInForeignJS = wasInForeignJS; |
| 2506 |
2482 // `throw` is emitted as a statement by `parseForeignJS`. | 2507 // `throw` is emitted as a statement by `parseForeignJS`. |
2483 assert(result is JS.Expression || node.parent is ExpressionStatement); | 2508 assert(result is JS.Expression || node.parent is ExpressionStatement); |
2484 return result; | 2509 return result; |
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) => |
(...skipping 1733 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 |