| 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 library dev_compiler.src.codegen.js_codegen; | 5 library dev_compiler.src.codegen.js_codegen; |
| 6 | 6 |
| 7 import 'dart:collection' show HashSet, HashMap; | 7 import 'dart:collection' show HashSet, HashMap; |
| 8 import 'dart:io' show Directory, File; | 8 import 'dart:io' show Directory, File; |
| 9 | 9 |
| 10 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; | 10 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; |
| (...skipping 597 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 608 node.name == null) { | 608 node.name == null) { |
| 609 // Implements Dart constructor behavior. Because of V8 `super` | 609 // Implements Dart constructor behavior. Because of V8 `super` |
| 610 // [constructor restrictions] | 610 // [constructor restrictions] |
| 611 // (https://code.google.com/p/v8/issues/detail?id=3330#c65) | 611 // (https://code.google.com/p/v8/issues/detail?id=3330#c65) |
| 612 // we cannot currently emit actual ES6 constructors with super calls. | 612 // we cannot currently emit actual ES6 constructors with super calls. |
| 613 // Instead we use the same trick as named constructors, and do them as | 613 // Instead we use the same trick as named constructors, and do them as |
| 614 // instance methods that perform initialization. | 614 // instance methods that perform initialization. |
| 615 // TODO(jmesserly): we'll need to rethink this once the ES6 spec and V8 | 615 // TODO(jmesserly): we'll need to rethink this once the ES6 spec and V8 |
| 616 // settles. See <https://github.com/dart-lang/dev_compiler/issues/51>. | 616 // settles. See <https://github.com/dart-lang/dev_compiler/issues/51>. |
| 617 // Performance of this pattern is likely to be bad. | 617 // Performance of this pattern is likely to be bad. |
| 618 name = 'constructor'; | 618 name = js.string('constructor', "'"); |
| 619 // Mark the parameter as no-rename. | 619 // Mark the parameter as no-rename. |
| 620 var args = new JS.Identifier('arguments', allowRename: false); | 620 var args = new JS.Identifier('arguments', allowRename: false); |
| 621 body = js.statement('''{ | 621 body = js.statement('''{ |
| 622 // Get the class name for this instance. | 622 // Get the class name for this instance. |
| 623 var name = this.constructor.name; | 623 var name = this.constructor.name; |
| 624 // Call the default constructor. | 624 // Call the default constructor. |
| 625 var init = this[name]; | 625 var init = this[name]; |
| 626 var result = void 0; | 626 var result = void 0; |
| 627 if (init) result = init.apply(this, #); | 627 if (init) result = init.apply(this, #); |
| 628 return result === void 0 ? this : result; | 628 return result === void 0 ? this : result; |
| 629 }''', args); | 629 }''', args); |
| 630 } else { | 630 } else { |
| 631 body = _emitConstructorBody(node, fields); | 631 body = _emitConstructorBody(node, fields); |
| 632 } | 632 } |
| 633 | 633 |
| 634 // We generate constructors as initializer methods in the class; | 634 // We generate constructors as initializer methods in the class; |
| 635 // this allows use of `super` for instance methods/properties. | 635 // this allows use of `super` for instance methods/properties. |
| 636 // It also avoids V8 restrictions on `super` in default constructors. | 636 // It also avoids V8 restrictions on `super` in default constructors. |
| 637 return new JS.Method( | 637 return new JS.Method(name, new JS.Fun(_visit(node.parameters), body)) |
| 638 _propertyName(name), new JS.Fun(_visit(node.parameters), body)) | |
| 639 ..sourceInformation = node; | 638 ..sourceInformation = node; |
| 640 } | 639 } |
| 641 | 640 |
| 642 String _constructorName(String className, SimpleIdentifier name) { | 641 JS.Expression _constructorName(String className, SimpleIdentifier name) { |
| 643 if (name == null) return className; | 642 if (name == null) return js.string(className, "'"); |
| 644 return '$className\$${name.name}'; | 643 return _jsMemberName(name.name, isStatic: true); |
| 645 } | 644 } |
| 646 | 645 |
| 647 JS.Block _emitConstructorBody( | 646 JS.Block _emitConstructorBody( |
| 648 ConstructorDeclaration node, List<FieldDeclaration> fields) { | 647 ConstructorDeclaration node, List<FieldDeclaration> fields) { |
| 649 // Wacky factory redirecting constructors: factory Foo.q(x, y) = Bar.baz; | 648 // Wacky factory redirecting constructors: factory Foo.q(x, y) = Bar.baz; |
| 650 if (node.redirectedConstructor != null) { | 649 if (node.redirectedConstructor != null) { |
| 651 return js.statement('{ return new #(#); }', [ | 650 return js.statement('{ return new #(#); }', [ |
| 652 _visit(node.redirectedConstructor), | 651 _visit(node.redirectedConstructor), |
| 653 _visit(node.parameters) | 652 _visit(node.parameters) |
| 654 ]); | 653 ]); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 694 return new JS.Block(body)..sourceInformation = node; | 693 return new JS.Block(body)..sourceInformation = node; |
| 695 } | 694 } |
| 696 | 695 |
| 697 @override | 696 @override |
| 698 JS.Statement visitRedirectingConstructorInvocation( | 697 JS.Statement visitRedirectingConstructorInvocation( |
| 699 RedirectingConstructorInvocation node) { | 698 RedirectingConstructorInvocation node) { |
| 700 ClassDeclaration classDecl = node.parent.parent; | 699 ClassDeclaration classDecl = node.parent.parent; |
| 701 var className = classDecl.name.name; | 700 var className = classDecl.name.name; |
| 702 | 701 |
| 703 var name = _constructorName(className, node.constructorName); | 702 var name = _constructorName(className, node.constructorName); |
| 704 return js.statement( | 703 return js.statement('this.#(#);', [name, _visit(node.argumentList)]); |
| 705 'this.#(#);', [_jsMemberName(name), _visit(node.argumentList)]); | |
| 706 } | 704 } |
| 707 | 705 |
| 708 JS.Statement _superConstructorCall(ClassDeclaration clazz, | 706 JS.Statement _superConstructorCall(ClassDeclaration clazz, |
| 709 [SuperConstructorInvocation node]) { | 707 [SuperConstructorInvocation node]) { |
| 710 var superCtorName = node != null ? node.constructorName : null; | 708 var superCtorName = node != null ? node.constructorName : null; |
| 711 | 709 |
| 712 var element = clazz.element; | 710 var element = clazz.element; |
| 713 if (superCtorName == null && | 711 if (superCtorName == null && |
| 714 (element.type.isObject || element.supertype.isObject)) { | 712 (element.type.isObject || element.supertype.isObject)) { |
| 715 return null; | 713 return null; |
| (...skipping 624 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1340 | 1338 |
| 1341 @override | 1339 @override |
| 1342 JS.Statement visitVariableDeclarationStatement( | 1340 JS.Statement visitVariableDeclarationStatement( |
| 1343 VariableDeclarationStatement node) => | 1341 VariableDeclarationStatement node) => |
| 1344 _expressionStatement(_visit(node.variables)); | 1342 _expressionStatement(_visit(node.variables)); |
| 1345 | 1343 |
| 1346 @override | 1344 @override |
| 1347 visitConstructorName(ConstructorName node) { | 1345 visitConstructorName(ConstructorName node) { |
| 1348 var typeName = _visit(node.type.name); | 1346 var typeName = _visit(node.type.name); |
| 1349 if (node.name != null) { | 1347 if (node.name != null) { |
| 1350 return js.call('#.#', [typeName, node.name.name]); | 1348 return js.call( |
| 1349 '#.#', [typeName, _jsMemberName(node.name.name, isStatic: true)]); |
| 1351 } | 1350 } |
| 1352 return typeName; | 1351 return typeName; |
| 1353 } | 1352 } |
| 1354 | 1353 |
| 1355 @override | 1354 @override |
| 1356 visitInstanceCreationExpression(InstanceCreationExpression node) { | 1355 visitInstanceCreationExpression(InstanceCreationExpression node) { |
| 1357 return js.call( | 1356 return js.call( |
| 1358 'new #(#)', [_visit(node.constructorName), _visit(node.argumentList)]); | 1357 'new #(#)', [_visit(node.constructorName), _visit(node.argumentList)]); |
| 1359 } | 1358 } |
| 1360 | 1359 |
| (...skipping 993 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2354 | 2353 |
| 2355 // TODO(jmesserly): in many cases marking the end will be unncessary. | 2354 // TODO(jmesserly): in many cases marking the end will be unncessary. |
| 2356 printer.mark(_location(node.end)); | 2355 printer.mark(_location(node.end)); |
| 2357 } | 2356 } |
| 2358 | 2357 |
| 2359 String _getIdentifier(AstNode node) { | 2358 String _getIdentifier(AstNode node) { |
| 2360 if (node is SimpleIdentifier) return node.name; | 2359 if (node is SimpleIdentifier) return node.name; |
| 2361 return null; | 2360 return null; |
| 2362 } | 2361 } |
| 2363 } | 2362 } |
| OLD | NEW |