| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 | 5 |
| 6 /** | 6 /** |
| 7 * If true, print a warning for each method that was resolved, but not | 7 * If true, print a warning for each method that was resolved, but not |
| 8 * compiled. | 8 * compiled. |
| 9 */ | 9 */ |
| 10 const bool REPORT_EXCESS_RESOLUTION = false; | 10 const bool REPORT_EXCESS_RESOLUTION = false; |
| (...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 389 } | 389 } |
| 390 | 390 |
| 391 void patchDartLibrary(LibraryElement library, String dartLibraryPath) { | 391 void patchDartLibrary(LibraryElement library, String dartLibraryPath) { |
| 392 if (library.isPatched) return; | 392 if (library.isPatched) return; |
| 393 Uri patchUri = resolvePatchUri(dartLibraryPath); | 393 Uri patchUri = resolvePatchUri(dartLibraryPath); |
| 394 if (patchUri !== null) { | 394 if (patchUri !== null) { |
| 395 patchParser.patchLibrary(patchUri, library); | 395 patchParser.patchLibrary(patchUri, library); |
| 396 } | 396 } |
| 397 } | 397 } |
| 398 | 398 |
| 399 void applyContainerPatch(ScopeContainerElement original, | |
| 400 Link<Element> patches) { | |
| 401 while (!patches.isEmpty()) { | |
| 402 Element patchElement = patches.head; | |
| 403 Element originalElement = original.localLookup(patchElement.name); | |
| 404 if (patchElement.isAccessor() && originalElement !== null) { | |
| 405 if (originalElement.kind !== ElementKind.ABSTRACT_FIELD) { | |
| 406 internalError("Cannot patch non-getter/setter with getter/setter", | |
| 407 element: originalElement); | |
| 408 } | |
| 409 AbstractFieldElement originalField = originalElement; | |
| 410 if (patchElement.isGetter()) { | |
| 411 originalElement = originalField.getter; | |
| 412 } else { | |
| 413 originalElement = originalField.setter; | |
| 414 } | |
| 415 } | |
| 416 if (originalElement === null) { | |
| 417 if (isPatchElement(patchElement)) { | |
| 418 internalError("Cannot patch non-existing member '" | |
| 419 "${patchElement.name.slowToString()}'."); | |
| 420 } | |
| 421 } else { | |
| 422 patchMember(originalElement, patchElement); | |
| 423 } | |
| 424 patches = patches.tail; | |
| 425 } | |
| 426 } | |
| 427 | |
| 428 bool isPatchElement(Element element) { | |
| 429 // TODO(lrn): More checks needed if we introduce metadata for real. | |
| 430 // In that case, it must have the identifier "native" as metadata. | |
| 431 for (Link link = element.metadata; !link.isEmpty(); link = link.tail) { | |
| 432 if (link.head is PatchMetadataAnnotation) return true; | |
| 433 } | |
| 434 return false; | |
| 435 } | |
| 436 | |
| 437 Element clonePatch(Element patchElement, Element enclosing) { | |
| 438 // The original library does not have an element with the same name | |
| 439 // as the patch library element. | |
| 440 // In this case, the patch library element must not be marked as "patch", | |
| 441 // and its name must make it private. | |
| 442 if (!patchElement.name.isPrivate()) { | |
| 443 internalError("Cannot add non-private member '" | |
| 444 "${patchElement.name.slowToString()}' from patch."); | |
| 445 } | |
| 446 Element override = | |
| 447 new CompilationUnitOverrideElement(patchElement.getCompilationUnit(), | |
| 448 enclosing); | |
| 449 return patchElement.cloneTo(override, this); | |
| 450 } | |
| 451 | |
| 452 void patchMember(Element originalElement, Element patchElement) { | |
| 453 // The original library has an element with the same name as the patch | |
| 454 // library element. | |
| 455 // In this case, the patch library element must be a function marked as | |
| 456 // "patch" and it must have the same signature as the function it patches. | |
| 457 if (!isPatchElement(patchElement)) { | |
| 458 internalError("Cannot overwrite existing '" | |
| 459 "${originalElement.name.slowToString()}' with non-patch."); | |
| 460 } | |
| 461 if (originalElement is! FunctionElement) { | |
| 462 // TODO(lrn): Handle class declarations too. | |
| 463 internalError("Can only patch functions", element: originalElement); | |
| 464 } | |
| 465 FunctionElement original = originalElement; | |
| 466 if (!original.modifiers.isExternal()) { | |
| 467 internalError("Can only patch external functions.", element: original); | |
| 468 } | |
| 469 if (patchElement is! FunctionElement || | |
| 470 !patchSignatureMatches(original, patchElement)) { | |
| 471 internalError("Can only patch functions with matching signatures", | |
| 472 element: original); | |
| 473 } | |
| 474 applyFunctionPatch(original, patchElement); | |
| 475 } | |
| 476 | |
| 477 bool patchSignatureMatches(FunctionElement original, FunctionElement patch) { | |
| 478 // TODO(lrn): Check that patches actually match the signature of | |
| 479 // the function it's patching. | |
| 480 return true; | |
| 481 } | |
| 482 | |
| 483 void applyFunctionPatch(FunctionElement element, | |
| 484 FunctionElement patchElement) { | |
| 485 if (element.isPatched) { | |
| 486 internalError("Trying to patch a function more than once.", | |
| 487 element: element); | |
| 488 } | |
| 489 if (element.cachedNode !== null) { | |
| 490 internalError("Trying to patch an already compiled function.", | |
| 491 element: element); | |
| 492 } | |
| 493 // Don't just assign the patch field. This also updates the cachedNode. | |
| 494 element.setPatch(patchElement); | |
| 495 patchElement.origin = element; | |
| 496 } | |
| 497 | |
| 498 /** | 399 /** |
| 499 * Get an [Uri] pointing to a patch for the dart: library with | 400 * Get an [Uri] pointing to a patch for the dart: library with |
| 500 * the given path. Returns null if there is no patch. | 401 * the given path. Returns null if there is no patch. |
| 501 */ | 402 */ |
| 502 abstract Uri resolvePatchUri(String dartLibraryPath); | 403 abstract Uri resolvePatchUri(String dartLibraryPath); |
| 503 | 404 |
| 504 /** Define the JS helper functions in the given library. */ | 405 /** Define the JS helper functions in the given library. */ |
| 505 void addForeignFunctions(LibraryElement library) { | 406 void addForeignFunctions(LibraryElement library) { |
| 506 library.addToScope(new ForeignElement( | 407 library.addToScope(new ForeignElement( |
| 507 const SourceString('JS'), library), this); | 408 const SourceString('JS'), library), this); |
| (...skipping 432 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 940 * information in the generated error message. | 841 * information in the generated error message. |
| 941 */ | 842 */ |
| 942 bool invariant(Spannable spannable, var condition, {String message: null}) { | 843 bool invariant(Spannable spannable, var condition, {String message: null}) { |
| 943 // TODO(johnniwinther): Use [spannable] and [message] to provide better | 844 // TODO(johnniwinther): Use [spannable] and [message] to provide better |
| 944 // information on assertion errors. | 845 // information on assertion errors. |
| 945 if (condition is Function){ | 846 if (condition is Function){ |
| 946 condition = condition(); | 847 condition = condition(); |
| 947 } | 848 } |
| 948 return spannable != null && condition; | 849 return spannable != null && condition; |
| 949 } | 850 } |
| OLD | NEW |