Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(412)

Side by Side Diff: lib/src/codegen/js_codegen.dart

Issue 1580413002: Add a `@JSExportName` annotation for internal use in the runtime (use it to export dart.assert inst… (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: made _emitTopLevelName.suffix a named arg Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « lib/runtime/dart/_utils.js ('k') | lib/src/codegen/js_interop.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 dev_compiler.src.codegen.js_codegen; 5 library dev_compiler.src.codegen.js_codegen;
6 6
7 import 'dart:collection' show HashSet, HashMap, SplayTreeSet; 7 import 'dart:collection' show HashSet, HashMap, SplayTreeSet;
8 8
9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; 9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator;
10 import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator; 10 import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator;
(...skipping 1276 matching lines...) Expand 10 before | Expand all | Expand 10 after
1287 } 1287 }
1288 1288
1289 return annotate( 1289 return annotate(
1290 new JS.Method(_elementMemberName(node.element), fn, 1290 new JS.Method(_elementMemberName(node.element), fn,
1291 isGetter: node.isGetter, 1291 isGetter: node.isGetter,
1292 isSetter: node.isSetter, 1292 isSetter: node.isSetter,
1293 isStatic: node.isStatic), 1293 isStatic: node.isStatic),
1294 node.element); 1294 node.element);
1295 } 1295 }
1296 1296
1297 /// Returns the name value of the `JSExportName` annotation (when compiling
1298 /// the SDK), or `null` if there's none. This is used to control the name
1299 /// under which functions are compiled and exported.
1300 String _getJSExportName(Element e) {
1301 if (e is! FunctionElement || !currentLibrary.source.isInSystemLibrary) {
1302 return null;
1303 }
1304 var jsName = findAnnotation(e, isJSExportNameAnnotation);
1305 return getConstantField(jsName, 'name', types.stringType)?.toStringValue();
1306 }
1307
1297 @override 1308 @override
1298 JS.Statement visitFunctionDeclaration(FunctionDeclaration node) { 1309 JS.Statement visitFunctionDeclaration(FunctionDeclaration node) {
1299 assert(node.parent is CompilationUnit); 1310 assert(node.parent is CompilationUnit);
1300 1311
1301 if (_externalOrNative(node)) return null; 1312 if (_externalOrNative(node)) return null;
1302 1313
1303 if (node.isGetter || node.isSetter) { 1314 if (node.isGetter || node.isSetter) {
1304 // Add these later so we can use getter/setter syntax. 1315 // Add these later so we can use getter/setter syntax.
1305 _properties.add(node); 1316 _properties.add(node);
1306 return null; 1317 return null;
1307 } 1318 }
1308 1319
1309 var body = <JS.Statement>[]; 1320 var body = <JS.Statement>[];
1310 _flushLibraryProperties(body); 1321 _flushLibraryProperties(body);
1311 1322
1312 var name = node.name.name; 1323 var name = _getJSExportName(node.element) ?? node.name.name;
1313 1324
1314 var fn = _visit(node.functionExpression); 1325 var fn = _visit(node.functionExpression);
1315 bool needsTagging = true; 1326 bool needsTagging = true;
1316 1327
1317 if (currentLibrary.source.isInSystemLibrary && 1328 if (currentLibrary.source.isInSystemLibrary &&
1318 _isInlineJSFunction(node.functionExpression)) { 1329 _isInlineJSFunction(node.functionExpression)) {
1319 fn = _simplifyPassThroughArrowFunCallBody(fn); 1330 fn = _simplifyPassThroughArrowFunCallBody(fn);
1320 needsTagging = !_isDartUtils; 1331 needsTagging = !_isDartUtils;
1321 } 1332 }
1322 1333
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after
1568 } 1579 }
1569 1580
1570 // Get the original declaring element. If we had a property accessor, this 1581 // Get the original declaring element. If we had a property accessor, this
1571 // indirects back to a (possibly synthetic) field. 1582 // indirects back to a (possibly synthetic) field.
1572 var element = accessor; 1583 var element = accessor;
1573 if (accessor is PropertyAccessorElement) element = accessor.variable; 1584 if (accessor is PropertyAccessorElement) element = accessor.variable;
1574 if (accessor is FunctionMember) element = accessor.baseElement; 1585 if (accessor is FunctionMember) element = accessor.baseElement;
1575 1586
1576 _loader.declareBeforeUse(element); 1587 _loader.declareBeforeUse(element);
1577 1588
1578 var name = element.name;
1579
1580 // type literal 1589 // type literal
1581 if (element is ClassElement || 1590 if (element is ClassElement ||
1582 element is DynamicElementImpl || 1591 element is DynamicElementImpl ||
1583 element is FunctionTypeAliasElement) { 1592 element is FunctionTypeAliasElement) {
1584 return _emitTypeName( 1593 return _emitTypeName(
1585 fillDynamicTypeArgs((element as dynamic).type, types)); 1594 fillDynamicTypeArgs((element as dynamic).type, types));
1586 } 1595 }
1587 1596
1588 // library member 1597 // library member
1589 if (element.enclosingElement is CompilationUnitElement) { 1598 if (element.enclosingElement is CompilationUnitElement) {
1590 return _maybeQualifiedName(element); 1599 return _emitTopLevelName(element);
1591 } 1600 }
1592 1601
1602 var name = element.name;
1603
1593 // Unqualified class member. This could mean implicit-this, or implicit 1604 // Unqualified class member. This could mean implicit-this, or implicit
1594 // call to a static from the same class. 1605 // call to a static from the same class.
1595 if (element is ClassMemberElement && element is! ConstructorElement) { 1606 if (element is ClassMemberElement && element is! ConstructorElement) {
1596 bool isStatic = element.isStatic; 1607 bool isStatic = element.isStatic;
1597 var type = element.enclosingElement.type; 1608 var type = element.enclosingElement.type;
1598 var member = _emitMemberName(name, isStatic: isStatic, type: type); 1609 var member = _emitMemberName(name, isStatic: isStatic, type: type);
1599 1610
1600 // For static methods, we add the raw type name, without generics or 1611 // For static methods, we add the raw type name, without generics or
1601 // library prefix. We don't need those because static calls can't use 1612 // library prefix. We don't need those because static calls can't use
1602 // the generic type. 1613 // the generic type.
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
1750 if (args 1761 if (args
1751 .any((a) => a != types.dynamicType && !_isGenericTypeParameter(a))) { 1762 .any((a) => a != types.dynamicType && !_isGenericTypeParameter(a))) {
1752 jsArgs = args.map(_emitTypeName); 1763 jsArgs = args.map(_emitTypeName);
1753 } else if (lowerGeneric || isCurrentClass) { 1764 } else if (lowerGeneric || isCurrentClass) {
1754 // When creating a `new S<dynamic>` we try and use the raw form 1765 // When creating a `new S<dynamic>` we try and use the raw form
1755 // `new S()`, but this does not work if we're inside the same class, 1766 // `new S()`, but this does not work if we're inside the same class,
1756 // because `S` refers to the current S<T> we are generating. 1767 // because `S` refers to the current S<T> we are generating.
1757 jsArgs = []; 1768 jsArgs = [];
1758 } 1769 }
1759 if (jsArgs != null) { 1770 if (jsArgs != null) {
1760 var genericName = _maybeQualifiedName(element, '$name\$'); 1771 var genericName = _emitTopLevelName(element, suffix: '\$');
1761 return js.call('#(#)', [genericName, jsArgs]); 1772 return js.call('#(#)', [genericName, jsArgs]);
1762 } 1773 }
1763 } 1774 }
1764 1775
1765 return _maybeQualifiedName(element); 1776 return _emitTopLevelName(element);
1766 } 1777 }
1767 1778
1768 JS.Expression _maybeQualifiedName(Element e, [String name]) { 1779 JS.Expression _emitTopLevelName(Element e, {String suffix : ''}) {
1769 var libName = _libraryName(e.library); 1780 var libName = _libraryName(e.library);
1770 var nameExpr = _propertyName(name ?? e.name); 1781 var nameExpr = _propertyName((_getJSExportName(e) ?? e.name) + suffix);
1771 1782
1772 // Always qualify: 1783 // Always qualify:
1773 // * mutable top-level fields 1784 // * mutable top-level fields
1774 // * elements from other libraries 1785 // * elements from other libraries
1775 bool mutableTopLevel = e is TopLevelVariableElement && 1786 bool mutableTopLevel = e is TopLevelVariableElement &&
1776 !e.isConst && 1787 !e.isConst &&
1777 !_isFinalJSDecl(e.computeNode()); 1788 !_isFinalJSDecl(e.computeNode());
1778 bool fromAnotherLibrary = e.library != currentLibrary; 1789 bool fromAnotherLibrary = e.library != currentLibrary;
1779 if (mutableTopLevel || fromAnotherLibrary) { 1790 if (mutableTopLevel || fromAnotherLibrary) {
1780 return new JS.PropertyAccess(libName, nameExpr); 1791 return new JS.PropertyAccess(libName, nameExpr);
(...skipping 443 matching lines...) Expand 10 before | Expand all | Expand 10 after
2224 jsInit = _visitInitializer(field); 2235 jsInit = _visitInitializer(field);
2225 eagerInit = false; 2236 eagerInit = false;
2226 } 2237 }
2227 2238
2228 // Treat `final x = JS('', '...')` as a const (non-lazy) to help compile 2239 // Treat `final x = JS('', '...')` as a const (non-lazy) to help compile
2229 // runtime helpers. 2240 // runtime helpers.
2230 var isJSTopLevel = field.isFinal && _isFinalJSDecl(field); 2241 var isJSTopLevel = field.isFinal && _isFinalJSDecl(field);
2231 if (isJSTopLevel) eagerInit = true; 2242 if (isJSTopLevel) eagerInit = true;
2232 2243
2233 var fieldName = field.name.name; 2244 var fieldName = field.name.name;
2245 if (element is TopLevelVariableElement) {
2246 fieldName = _getJSExportName(element) ?? fieldName;
2247 }
2234 if ((field.isConst && eagerInit && element is TopLevelVariableElement) || 2248 if ((field.isConst && eagerInit && element is TopLevelVariableElement) ||
2235 isJSTopLevel) { 2249 isJSTopLevel) {
2236 // constant fields don't change, so we can generate them as `let` 2250 // constant fields don't change, so we can generate them as `let`
2237 // but add them to the module's exports. However, make sure we generate 2251 // but add them to the module's exports. However, make sure we generate
2238 // anything they depend on first. 2252 // anything they depend on first.
2239 2253
2240 if (isPublic(fieldName)) _addExport(fieldName); 2254 if (isPublic(fieldName)) _addExport(fieldName);
2241 var declKeyword = field.isConst || field.isFinal ? 'const' : 'let'; 2255 var declKeyword = field.isConst || field.isFinal ? 'const' : 'let';
2242 return annotateVariable( 2256 return annotateVariable(
2243 js.statement( 2257 js.statement(
(...skipping 1376 matching lines...) Expand 10 before | Expand all | Expand 10 after
3620 3634
3621 /// A special kind of element created by the compiler, signifying a temporary 3635 /// A special kind of element created by the compiler, signifying a temporary
3622 /// variable. These objects use instance equality, and should be shared 3636 /// variable. These objects use instance equality, and should be shared
3623 /// everywhere in the tree where they are treated as the same variable. 3637 /// everywhere in the tree where they are treated as the same variable.
3624 class TemporaryVariableElement extends LocalVariableElementImpl { 3638 class TemporaryVariableElement extends LocalVariableElementImpl {
3625 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); 3639 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name);
3626 3640
3627 int get hashCode => identityHashCode(this); 3641 int get hashCode => identityHashCode(this);
3628 bool operator ==(Object other) => identical(this, other); 3642 bool operator ==(Object other) => identical(this, other);
3629 } 3643 }
OLDNEW
« no previous file with comments | « lib/runtime/dart/_utils.js ('k') | lib/src/codegen/js_interop.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698