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

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

Issue 1341963003: qualify core types: Object, Error, Symbol (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 5 years, 3 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
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 273 matching lines...) Expand 10 before | Expand all | Expand 10 after
284 if (hide != null) { 284 if (hide != null) {
285 hiddenNames.addAll(hide.hiddenNames.map((i) => js.string(i.name, "'"))); 285 hiddenNames.addAll(hide.hiddenNames.map((i) => js.string(i.name, "'")));
286 } 286 }
287 args.add(new JS.ArrayInitializer(shownNames)); 287 args.add(new JS.ArrayInitializer(shownNames));
288 args.add(new JS.ArrayInitializer(hiddenNames)); 288 args.add(new JS.ArrayInitializer(hiddenNames));
289 } 289 }
290 _moduleItems.add(js.statement('dart.export(#);', [args])); 290 _moduleItems.add(js.statement('dart.export(#);', [args]));
291 } 291 }
292 292
293 JS.Identifier _initSymbol(JS.Identifier id) { 293 JS.Identifier _initSymbol(JS.Identifier id) {
294 var s = js.statement('let # = $_SYMBOL(#);', [id, js.string(id.name, "'")]); 294 var s = js.statement('let # = Symbol(#);', [id, js.string(id.name, "'")]);
295 _moduleItems.add(s); 295 _moduleItems.add(s);
296 return id; 296 return id;
297 } 297 }
298 298
299 // TODO(jmesserly): this is a temporary workaround for `Symbol` in core,
300 // until we have better name tracking.
301 String get _SYMBOL {
302 var name = currentLibrary.name;
303 if (name == 'dart.core' || name == 'dart._internal') return 'dart.JsSymbol';
304 return 'Symbol';
305 }
306
307 bool isPublic(String name) => !name.startsWith('_'); 299 bool isPublic(String name) => !name.startsWith('_');
308 300
309 @override 301 @override
310 visitAsExpression(AsExpression node) { 302 visitAsExpression(AsExpression node) {
311 var from = getStaticType(node.expression); 303 var from = getStaticType(node.expression);
312 var to = node.type.type; 304 var to = node.type.type;
313 305
314 // Skip the cast if it's not needed. 306 // Skip the cast if it's not needed.
315 if (rules.isSubTypeOf(from, to)) return _visit(node.expression); 307 if (rules.isSubTypeOf(from, to)) return _visit(node.expression);
316 308
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after
544 return js.statement( 536 return js.statement(
545 '{ #; dart.defineLazyClassGeneric(#, #, { get: # }); }', 537 '{ #; dart.defineLazyClassGeneric(#, #, { get: # }); }',
546 [genericDef, _exportsVar, _propertyName(name), genericName]); 538 [genericDef, _exportsVar, _propertyName(name), genericName]);
547 } 539 }
548 540
549 return js.statement( 541 return js.statement(
550 'dart.defineLazyClass(#, { get #() { #; return #; } });', 542 'dart.defineLazyClass(#, { get #() { #; return #; } });',
551 [_exportsVar, _propertyName(name), body, name]); 543 [_exportsVar, _propertyName(name), body, name]);
552 } 544 }
553 545
554 if (isPublic(name)) _addExport(name);
555
556 if (genericDef != null) { 546 if (genericDef != null) {
557 var dynType = fillDynamicTypeArgs(type, types); 547 var dynType = fillDynamicTypeArgs(type, types);
558 var genericInst = _emitTypeName(dynType, lowerGeneric: true); 548 var genericInst = _emitTypeName(dynType, lowerGeneric: true);
559 return js.statement('{ #; let # = #; }', [genericDef, name, genericInst]); 549
550 if (_isJsBuiltinName(name)) {
ochafik 2015/09/15 18:05:17 nit: store as a var above for reuse below?
551 genericInst = js.statement('#.# = #;',
552 [_libraryName(type.element.library), name, genericInst]);
ochafik 2015/09/15 18:05:17 nit: isn't this guaranteed to be currentLibrary?
553 } else {
554 if (isPublic(name)) _addExport(name);
555 genericInst = js.statement('let # = #;', [name, genericInst]);
556 }
557
558 return new JS.Block([genericDef, genericInst]);
560 } 559 }
560
561 if (_isJsBuiltinName(name)) {
562 var typeName = _emitTypeName(type) as JS.PropertyAccess;
563
564 // TODO(jmesserly): we could generate something cleaner, but since it only
565 // affects 3 types, doesn't seem like a big concern.
566 var classExpr = new JS.Call(
567 new JS.ArrowFun([], js.statement('{ #; return #; }', [body, name])),
568 []);
569 return new JS.Assignment(typeName, classExpr).toStatement();
570 } else if (isPublic(name)) {
571 _addExport(name);
572 }
573
561 return body; 574 return body;
562 } 575 }
563 576
564 JS.Statement _emitGenericClassDef(ParameterizedType type, JS.Statement body) { 577 JS.Statement _emitGenericClassDef(ParameterizedType type, JS.Statement body) {
565 var name = type.name; 578 var name = type.name;
566 var genericName = '$name\$'; 579 var genericName = '$name\$';
567 var typeParams = type.typeParameters.map((p) => p.name); 580 var typeParams = type.typeParameters.map((p) => p.name);
568 if (isPublic(name)) _exports.add(genericName); 581 if (isPublic(name)) _exports.add(genericName);
569 return js.statement('let # = dart.generic(function(#) { #; return #; });', 582 return js.statement('let # = dart.generic(function(#) { #; return #; });',
570 [genericName, typeParams, body, name]); 583 [genericName, typeParams, body, name]);
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
648 // Iterable, we know the adapter is already there, so we can skip it as a 661 // Iterable, we know the adapter is already there, so we can skip it as a
649 // simple code size optimization. 662 // simple code size optimization.
650 var parent = t.lookUpGetterInSuperclass('iterator', t.element.library); 663 var parent = t.lookUpGetterInSuperclass('iterator', t.element.library);
651 if (parent != null) return null; 664 if (parent != null) return null;
652 var parentType = findSupertype(t, _implementsIterable); 665 var parentType = findSupertype(t, _implementsIterable);
653 if (parentType != null) return null; 666 if (parentType != null) return null;
654 667
655 // Otherwise, emit the adapter method, which wraps the Dart iterator in 668 // Otherwise, emit the adapter method, which wraps the Dart iterator in
656 // an ES6 iterator. 669 // an ES6 iterator.
657 return new JS.Method( 670 return new JS.Method(
658 js.call('$_SYMBOL.iterator'), 671 js.call('Symbol.iterator'),
659 js.call('function() { return new dart.JsIterator(this.#); }', 672 js.call('function() { return new dart.JsIterator(this.#); }',
660 [_emitMemberName('iterator', type: t)]) as JS.Fun); 673 [_emitMemberName('iterator', type: t)]) as JS.Fun);
661 } 674 }
662 675
663 JS.Expression _instantiateAnnotation(Annotation node) { 676 JS.Expression _instantiateAnnotation(Annotation node) {
664 var element = node.element; 677 var element = node.element;
665 if (element is ConstructorElement) { 678 if (element is ConstructorElement) {
666 return _emitInstanceCreationExpression(element, element.returnType, 679 return _emitInstanceCreationExpression(element, element.returnType,
667 node.constructorName, node.arguments, true); 680 node.constructorName, node.arguments, true);
668 } else { 681 } else {
(...skipping 979 matching lines...) Expand 10 before | Expand all | Expand 10 after
1648 return _maybeQualifiedName(element, _propertyName(name)); 1661 return _maybeQualifiedName(element, _propertyName(name));
1649 } 1662 }
1650 1663
1651 JS.Expression _maybeQualifiedName(Element e, JS.Expression name, 1664 JS.Expression _maybeQualifiedName(Element e, JS.Expression name,
1652 [Map<Element, JS.MaybeQualifiedId> idTable]) { 1665 [Map<Element, JS.MaybeQualifiedId> idTable]) {
1653 var libName = _libraryName(e.library); 1666 var libName = _libraryName(e.library);
1654 if (idTable == null) idTable = _qualifiedIds; 1667 if (idTable == null) idTable = _qualifiedIds;
1655 1668
1656 // Mutable top-level fields should always be qualified. 1669 // Mutable top-level fields should always be qualified.
1657 bool mutableTopLevel = e is TopLevelVariableElement && !e.isConst; 1670 bool mutableTopLevel = e is TopLevelVariableElement && !e.isConst;
1658 if (e.library != currentLibrary || mutableTopLevel) { 1671 if (e.library != currentLibrary ||
1672 mutableTopLevel ||
1673 _isJsBuiltinName(e.name)) {
ochafik 2015/09/15 18:05:17 I think that check alone (in the context of "exten
1659 return new JS.PropertyAccess(libName, name); 1674 return new JS.PropertyAccess(libName, name);
1660 } 1675 }
1661 1676
1662 return idTable.putIfAbsent(e, () => new JS.MaybeQualifiedId(libName, name)); 1677 return idTable.putIfAbsent(e, () => new JS.MaybeQualifiedId(libName, name));
1663 } 1678 }
1664 1679
1680 /// Returns true if this name is Object, Error, or Symbol.
1681 ///
1682 /// We avoid using those names as locals so we don't shadow the global JS
1683 /// names. While we could technically deal with this, it confuses other tools
1684 /// like JS Compiler.
1685 bool _isJsBuiltinName(String name) {
1686 switch (name) {
1687 case 'Object':
1688 case 'Error':
1689 case 'Symbol':
ochafik 2015/09/15 16:58:33 Presumably also Map, Set, TypeError, RangeError, R
Jennifer Messerly 2015/09/15 17:06:09 Maybe I need to step back, I honestly don't have a
ochafik 2015/09/15 18:05:17 Right now it's just to avoid errors in Closure wit
Jennifer Messerly 2015/09/15 18:34:23 ah, we try and qualify the minimum possible. In fa
1690 return true;
1691 }
1692 return false;
1693 }
1694
1665 @override 1695 @override
1666 JS.Expression visitAssignmentExpression(AssignmentExpression node) { 1696 JS.Expression visitAssignmentExpression(AssignmentExpression node) {
1667 var left = node.leftHandSide; 1697 var left = node.leftHandSide;
1668 var right = node.rightHandSide; 1698 var right = node.rightHandSide;
1669 if (node.operator.type == TokenType.EQ) return _emitSet(left, right); 1699 if (node.operator.type == TokenType.EQ) return _emitSet(left, right);
1670 var op = node.operator.lexeme; 1700 var op = node.operator.lexeme;
1671 assert(op.endsWith('=')); 1701 assert(op.endsWith('='));
1672 op = op.substring(0, op.length - 1); // remove trailing '=' 1702 op = op.substring(0, op.length - 1); // remove trailing '='
1673 return _emitOpAssign(left, right, op, node.staticElement, context: node); 1703 return _emitOpAssign(left, right, op, node.staticElement, context: node);
1674 } 1704 }
(...skipping 1636 matching lines...) Expand 10 before | Expand all | Expand 10 after
3311 3341
3312 /// A special kind of element created by the compiler, signifying a temporary 3342 /// A special kind of element created by the compiler, signifying a temporary
3313 /// variable. These objects use instance equality, and should be shared 3343 /// variable. These objects use instance equality, and should be shared
3314 /// everywhere in the tree where they are treated as the same variable. 3344 /// everywhere in the tree where they are treated as the same variable.
3315 class TemporaryVariableElement extends LocalVariableElementImpl { 3345 class TemporaryVariableElement extends LocalVariableElementImpl {
3316 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); 3346 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name);
3317 3347
3318 int get hashCode => identityHashCode(this); 3348 int get hashCode => identityHashCode(this);
3319 bool operator ==(Object other) => identical(this, other); 3349 bool operator ==(Object other) => identical(this, other);
3320 } 3350 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698