| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 dart2js_incremental.library_updater; | 5 library dart2js_incremental.library_updater; |
| 6 | 6 |
| 7 import 'dart:async' show | 7 import 'dart:async' show |
| 8 Future; | 8 Future; |
| 9 | 9 |
| 10 import 'dart:convert' show | 10 import 'dart:convert' show |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 48 MemberInfo; | 48 MemberInfo; |
| 49 | 49 |
| 50 import 'package:_internal/compiler/js_lib/shared/embedded_names.dart' | 50 import 'package:_internal/compiler/js_lib/shared/embedded_names.dart' |
| 51 as embeddedNames; | 51 as embeddedNames; |
| 52 | 52 |
| 53 import 'package:compiler/src/js_backend/js_backend.dart' show | 53 import 'package:compiler/src/js_backend/js_backend.dart' show |
| 54 JavaScriptBackend, | 54 JavaScriptBackend, |
| 55 Namer; | 55 Namer; |
| 56 | 56 |
| 57 import 'package:compiler/src/util/util.dart' show | 57 import 'package:compiler/src/util/util.dart' show |
| 58 Link; | 58 Link, |
| 59 LinkBuilder; |
| 59 | 60 |
| 60 import 'package:compiler/src/elements/modelx.dart' show | 61 import 'package:compiler/src/elements/modelx.dart' show |
| 61 DeclarationSite, | 62 DeclarationSite, |
| 62 ElementX; | 63 ElementX; |
| 63 | 64 |
| 64 import 'diff.dart' show | 65 import 'diff.dart' show |
| 65 Difference, | 66 Difference, |
| 66 computeDifference; | 67 computeDifference; |
| 67 | 68 |
| 68 typedef void Logger(message); | 69 typedef void Logger(message); |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 222 | 223 |
| 223 bool canReuseRemovedElement(PartialElement element) { | 224 bool canReuseRemovedElement(PartialElement element) { |
| 224 if (element is PartialFunctionElement) { | 225 if (element is PartialFunctionElement) { |
| 225 return canReuseRemovedFunction(element); | 226 return canReuseRemovedFunction(element); |
| 226 } | 227 } |
| 227 return cannotReuse( | 228 return cannotReuse( |
| 228 element, "Removed element that isn't a method."); | 229 element, "Removed element that isn't a method."); |
| 229 } | 230 } |
| 230 | 231 |
| 231 bool canReuseRemovedFunction(PartialFunctionElement element) { | 232 bool canReuseRemovedFunction(PartialFunctionElement element) { |
| 232 if (!element.isInstanceMember) { | 233 logVerbose("Removed method $element."); |
| 233 return cannotReuse( | |
| 234 element, "Removed function that isn't an instance method."); | |
| 235 } | |
| 236 logVerbose("Removed instance method $element."); | |
| 237 | 234 |
| 238 PartialClassElement cls = element.enclosingClass; | 235 PartialClassElement cls = element.enclosingClass; |
| 236 if (cls != null && !element.isInstanceMember) { |
| 237 return cannotReuse(element, "Removed static method"); |
| 238 } |
| 239 for (ScopeContainerElement scope in scopesAffectedBy(element, cls)) { | 239 for (ScopeContainerElement scope in scopesAffectedBy(element, cls)) { |
| 240 scanSites(scope, (Element member, DeclarationSite site) { | 240 scanSites(scope, (Element member, DeclarationSite site) { |
| 241 // TODO(ahe): Cache qualifiedNamesIn to avoid quadratic behavior. | 241 // TODO(ahe): Cache qualifiedNamesIn to avoid quadratic behavior. |
| 242 Map<String, List<String>> names = qualifiedNamesIn(site); | 242 Map<String, List<String>> names = qualifiedNamesIn(site); |
| 243 if (canNamesResolveTo(names, element, cls)) { | 243 if (canNamesResolveTo(names, element, cls)) { |
| 244 _elementsToInvalidate.add(member); | 244 _elementsToInvalidate.add(member); |
| 245 } | 245 } |
| 246 }); | 246 }); |
| 247 } | 247 } |
| 248 | 248 |
| (...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 520 /// state. | 520 /// state. |
| 521 void reuseElement() { | 521 void reuseElement() { |
| 522 compiler.forgetElement(before); | 522 compiler.forgetElement(before); |
| 523 before.reuseElement(); | 523 before.reuseElement(); |
| 524 } | 524 } |
| 525 } | 525 } |
| 526 | 526 |
| 527 class RemovedFunctionUpdate extends Update with JsFeatures, ReuseFunction { | 527 class RemovedFunctionUpdate extends Update with JsFeatures, ReuseFunction { |
| 528 final PartialFunctionElement element; | 528 final PartialFunctionElement element; |
| 529 | 529 |
| 530 /// Name of property to remove using JavaScript "delete". | 530 /// Name of property to remove using JavaScript "delete". Null for |
| 531 /// non-instance methods. |
| 531 String name; | 532 String name; |
| 532 | 533 |
| 533 /// Name of super-alias property to remove using JavaScript "delete". Null | 534 /// Name of super-alias property to remove using JavaScript "delete". Null |
| 534 /// for methods that aren't "super aliased" (should imply that this field is | 535 /// for methods that aren't "super aliased", and non-instance methods. |
| 535 /// null for all non-instance methods). | |
| 536 String superName; | 536 String superName; |
| 537 | 537 |
| 538 /// For instance methods, access to class object. Otherwise, access to the |
| 539 /// method itself. |
| 540 jsAst.Node elementAccess; |
| 541 |
| 538 bool wasStateCaptured = false; | 542 bool wasStateCaptured = false; |
| 539 | 543 |
| 540 RemovedFunctionUpdate(Compiler compiler, this.element) | 544 RemovedFunctionUpdate(Compiler compiler, this.element) |
| 541 : super(compiler); | 545 : super(compiler); |
| 542 | 546 |
| 543 PartialFunctionElement get before => element; | 547 PartialFunctionElement get before => element; |
| 544 | 548 |
| 545 PartialElement get after => null; | 549 PartialElement get after => null; |
| 546 | 550 |
| 547 bool get isRemoval => true; | 551 bool get isRemoval => true; |
| 548 | 552 |
| 549 void captureState() { | 553 void captureState() { |
| 550 if (wasStateCaptured) throw "captureState was called twice."; | 554 if (wasStateCaptured) throw "captureState was called twice."; |
| 551 | 555 |
| 552 if (element.isInstanceMember) { | 556 if (element.isInstanceMember) { |
| 557 elementAccess = namer.elementAccess(element.enclosingClass); |
| 553 name = namer.getNameOfMember(element); | 558 name = namer.getNameOfMember(element); |
| 554 } | 559 if (backend.isAliasedSuperMember(element)) { |
| 555 if (backend.isAliasedSuperMember(element)) { | 560 superName = namer.getNameOfAliasedSuperMember(element); |
| 556 superName = namer.getNameOfAliasedSuperMember(element); | 561 } |
| 562 } else { |
| 563 elementAccess = namer.elementAccess(element); |
| 557 } | 564 } |
| 558 | 565 |
| 559 wasStateCaptured = true; | 566 wasStateCaptured = true; |
| 560 } | 567 } |
| 561 | 568 |
| 562 PartialElement apply() { | 569 PartialElement apply() { |
| 563 if (!wasStateCaptured) throw "captureState must be called before apply."; | 570 if (!wasStateCaptured) throw "captureState must be called before apply."; |
| 564 removeFromEnclosingClass(); | 571 removeFromEnclosing(); |
| 565 reuseElement(); | 572 reuseElement(); |
| 566 return null; | 573 return null; |
| 567 } | 574 } |
| 568 | 575 |
| 569 void removeFromEnclosingClass() { | 576 void removeFromEnclosing() { |
| 570 PartialClassElement cls = element.enclosingClass; | 577 PartialClassElement cls = element.enclosingClass; |
| 578 if (cls == null) { |
| 579 removeFromLibrary(element.library); |
| 580 } else { |
| 581 removeFromEnclosingClass(cls); |
| 582 } |
| 583 } |
| 571 | 584 |
| 572 Link<Element> localMembersReversed = const Link<Element>(); | 585 void removeFromEnclosingClass(PartialClassElement cls) { |
| 573 bool foundElement = false; | 586 cls.localMembersCache = null; |
| 574 cls.forEachLocalMember((member) { | 587 cls.localMembersReversed = |
| 575 if (member != element) { | 588 copyLinkWithout(element, cls.localMembersReversed); |
| 576 localMembersReversed = localMembersReversed.prepend(member); | 589 cls.localScope.contents.remove(element.name); |
| 577 } else { | 590 } |
| 578 if (foundElement) { | 591 |
| 579 throw "Found '$element' twice in '$cls'."; | 592 void removeFromLibrary(LibraryElementX library) { |
| 580 } | 593 library.localMembers = copyLinkWithout(element, library.localMembers); |
| 581 foundElement = true; | 594 library.localScope.contents.remove(element.name); |
| 595 } |
| 596 |
| 597 Link copyLinkWithout(e, Link link) { |
| 598 // TODO(ahe): Consider adding to [Link]. |
| 599 LinkBuilder copy = new LinkBuilder(); |
| 600 |
| 601 for (; !link.isEmpty; link = link.tail) { |
| 602 if (link.head != e) { |
| 603 copy.addLast(e); |
| 582 } | 604 } |
| 583 }); | |
| 584 if (!foundElement) { | |
| 585 throw "Don't find '$element' in '$cls'."; | |
| 586 } | 605 } |
| 587 cls.localMembersCache = null; | |
| 588 cls.localMembersReversed = localMembersReversed; | |
| 589 cls.localScope.contents.remove(element.name); | |
| 590 | 606 |
| 591 return null; | 607 return copy.toLink(link); |
| 592 } | 608 } |
| 593 | 609 |
| 594 void writeUpdateJsOn(List<jsAst.Statement> updates) { | 610 void writeUpdateJsOn(List<jsAst.Statement> updates) { |
| 595 if (name == null) { | 611 if (elementAccess == null) { |
| 596 compiler.internalError(element, '${element.runtimeType}'); | 612 compiler.internalError( |
| 613 element, 'No elementAccess for ${element.runtimeType}'); |
| 597 } | 614 } |
| 598 if (element.isInstanceMember) { | 615 if (element.isInstanceMember) { |
| 599 jsAst.Node elementAccess = namer.elementAccess(element.enclosingClass); | 616 if (name == null) { |
| 617 compiler.internalError(element, 'No name for ${element.runtimeType}'); |
| 618 } |
| 600 updates.add( | 619 updates.add( |
| 601 js.statement('delete #.prototype.#', [elementAccess, name])); | 620 js.statement('delete #.prototype.#', [elementAccess, name])); |
| 602 | 621 |
| 603 if (superName != null) { | 622 if (superName != null) { |
| 604 updates.add( | 623 updates.add( |
| 605 js.statement('delete #.prototype.#', [elementAccess, superName])); | 624 js.statement('delete #.prototype.#', [elementAccess, superName])); |
| 606 } | 625 } |
| 607 } else { | 626 } else { |
| 608 compiler.internalError( | 627 updates.add(js.statement('delete #', [elementAccess])); |
| 609 element, 'Removal of non-instance methods not yest supported.'); | |
| 610 } | 628 } |
| 611 } | 629 } |
| 612 } | 630 } |
| 613 | 631 |
| 614 Map<String, List<String>> qualifiedNamesIn(PartialElement element) { | 632 Map<String, List<String>> qualifiedNamesIn(PartialElement element) { |
| 615 Token beginToken = element.beginToken; | 633 Token beginToken = element.beginToken; |
| 616 Token endToken = element.endToken; | 634 Token endToken = element.endToken; |
| 617 Token token = beginToken; | 635 Token token = beginToken; |
| 618 if (element is PartialClassElement) { | 636 if (element is PartialClassElement) { |
| 619 ClassNode node = element.cachedNode; | 637 ClassNode node = element.cachedNode; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 664 | 682 |
| 665 abstract class JsFeatures { | 683 abstract class JsFeatures { |
| 666 Compiler get compiler; | 684 Compiler get compiler; |
| 667 | 685 |
| 668 JavaScriptBackend get backend => compiler.backend; | 686 JavaScriptBackend get backend => compiler.backend; |
| 669 | 687 |
| 670 Namer get namer => backend.namer; | 688 Namer get namer => backend.namer; |
| 671 | 689 |
| 672 CodeEmitterTask get emitter => backend.emitter; | 690 CodeEmitterTask get emitter => backend.emitter; |
| 673 } | 691 } |
| OLD | NEW |