| 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 final bool REPORT_EXCESS_RESOLUTION = false; | 10 final bool REPORT_EXCESS_RESOLUTION = false; |
| (...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 288 | 288 |
| 289 void onLibraryLoaded(LibraryElement library, Uri uri) { | 289 void onLibraryLoaded(LibraryElement library, Uri uri) { |
| 290 if (uri.toString() == 'dart:isolate') { | 290 if (uri.toString() == 'dart:isolate') { |
| 291 enableIsolateSupport(library); | 291 enableIsolateSupport(library); |
| 292 } | 292 } |
| 293 if (dynamicClass !== null) { | 293 if (dynamicClass !== null) { |
| 294 // When loading the built-in libraries, dynamicClass is null. We | 294 // When loading the built-in libraries, dynamicClass is null. We |
| 295 // take advantage of this as core and coreimpl import js_helper | 295 // take advantage of this as core and coreimpl import js_helper |
| 296 // and see Dynamic this way. | 296 // and see Dynamic this way. |
| 297 withCurrentElement(dynamicClass, () { | 297 withCurrentElement(dynamicClass, () { |
| 298 library.define(dynamicClass, this); | 298 library.addToScope(dynamicClass, this); |
| 299 }); | 299 }); |
| 300 } | 300 } |
| 301 } | 301 } |
| 302 | 302 |
| 303 abstract LibraryElement scanBuiltinLibrary(String filename); | 303 abstract LibraryElement scanBuiltinLibrary(String filename); |
| 304 | 304 |
| 305 void initializeSpecialClasses() { | 305 void initializeSpecialClasses() { |
| 306 bool coreLibValid = true; | 306 bool coreLibValid = true; |
| 307 ClassElement lookupSpecialClass(SourceString name) { | 307 ClassElement lookupSpecialClass(SourceString name) { |
| 308 ClassElement result = coreLibrary.find(name); | 308 ClassElement result = coreLibrary.find(name); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 367 if (patchUri !== null) { | 367 if (patchUri !== null) { |
| 368 LibraryElement patchLibrary = | 368 LibraryElement patchLibrary = |
| 369 patchParser.loadPatchLibrary(patchUri); | 369 patchParser.loadPatchLibrary(patchUri); |
| 370 // We allow foreign functions in patched libraries. | 370 // We allow foreign functions in patched libraries. |
| 371 addForeignFunctions(library); // Is safe even if already added. | 371 addForeignFunctions(library); // Is safe even if already added. |
| 372 applyLibraryPatch(library, patchLibrary); | 372 applyLibraryPatch(library, patchLibrary); |
| 373 } | 373 } |
| 374 } | 374 } |
| 375 | 375 |
| 376 void applyLibraryPatch(LibraryElement original, LibraryElement patch) { | 376 void applyLibraryPatch(LibraryElement original, LibraryElement patch) { |
| 377 Link<Element> patches = patch.topLevelElements; | 377 Link<Element> patches = patch.localMembers; |
| 378 applyContainerPatch(original, patches, original.findLocal); | 378 applyContainerPatch(original, patches); |
| 379 | 379 |
| 380 // Copy imports from patch to original library. | 380 // Copy imports from patch to original library. |
| 381 Map<String, LibraryElement> delayedPatches = <LibraryElement>{}; | 381 Map<String, LibraryElement> delayedPatches = <LibraryElement>{}; |
| 382 Uri patchBase = patch.script.uri; | 382 Uri patchBase = patch.uri; |
| 383 for (ScriptTag tag in patch.tags.reverse()) { | 383 for (ScriptTag tag in patch.tags.reverse()) { |
| 384 if (tag.isImport()) { | 384 if (tag.isImport()) { |
| 385 StringNode argument = tag.argument; | 385 StringNode argument = tag.argument; |
| 386 Uri resolved = patchBase.resolve(argument.dartString.slowToString()); | 386 Uri resolved = patchBase.resolve(argument.dartString.slowToString()); |
| 387 LibraryElement importedLibrary = | 387 LibraryElement importedLibrary = |
| 388 scanner.loadLibrary(resolved, argument); | 388 scanner.loadLibrary(resolved, argument); |
| 389 scanner.importLibrary(original, importedLibrary, tag, patch); | 389 scanner.importLibrary(original, importedLibrary, tag, |
| 390 patch.entryCompilationUnit); |
| 390 if (resolved.scheme == "dart") { | 391 if (resolved.scheme == "dart") { |
| 391 delayedPatches[resolved.path] = importedLibrary; | 392 delayedPatches[resolved.path] = importedLibrary; |
| 392 } | 393 } |
| 393 } | 394 } |
| 394 } | 395 } |
| 395 | 396 |
| 396 // Mark library as already patched. | 397 // Mark library as already patched. |
| 397 original.patch = patch; | 398 original.patch = patch; |
| 398 | 399 |
| 399 // We patch imported libraries after marking the current library as | 400 // We patch imported libraries after marking the current library as |
| 400 // patched, to avoid problems with cyclic dependencies. | 401 // patched, to avoid problems with cyclic dependencies. |
| 401 delayedPatches.forEach((String path, LibraryElement importedLibrary) { | 402 delayedPatches.forEach((String path, LibraryElement importedLibrary) { |
| 402 patchDartLibrary(importedLibrary, path); | 403 patchDartLibrary(importedLibrary, path); |
| 403 }); | 404 }); |
| 404 } | 405 } |
| 405 | 406 |
| 406 void applyContainerPatch(ContainerElement original, Link<Element> patches, | 407 void applyContainerPatch(ScopeContainerElement original, |
| 407 Element lookup(SourceString name)) { | 408 Link<Element> patches) { |
| 408 while (!patches.isEmpty()) { | 409 while (!patches.isEmpty()) { |
| 409 Element patchElement = patches.head; | 410 Element patchElement = patches.head; |
| 410 Element originalElement = lookup(patchElement.name); | 411 Element originalElement = original.localLookup(patchElement.name); |
| 411 if (patchElement.isAccessor()) { | 412 if (patchElement.isAccessor()) { |
| 412 // TODO(lrn): When we change to always add accessors to members, and | 413 // TODO(lrn): When we change to always add accessors to members, and |
| 413 // not add abstract fields, the logic here should be reversed. | 414 // not add abstract fields, the logic here should be reversed. |
| 414 // For now, access getters through the abstract field and skip | 415 // For now, access getters through the abstract field and skip |
| 415 // any accessors. | 416 // any accessors. |
| 416 } else if (patchElement.kind === ElementKind.ABSTRACT_FIELD) { | 417 } else if (patchElement.kind === ElementKind.ABSTRACT_FIELD) { |
| 417 // Getters and setters are kept inside a synthetic field. | 418 // Getters and setters are kept inside a synthetic field. |
| 418 if (originalElement !== null && | 419 if (originalElement !== null && |
| 419 originalElement.kind !== ElementKind.ABSTRACT_FIELD) { | 420 originalElement.kind !== ElementKind.ABSTRACT_FIELD) { |
| 420 internalError("Cannot patch non-getter/setter with getter/setter", | 421 internalError("Cannot patch non-getter/setter with getter/setter", |
| 421 element: originalElement); | 422 element: originalElement); |
| 422 } | 423 } |
| 423 AbstractFieldElement patchField = patchElement; | 424 AbstractFieldElement patchField = patchElement; |
| 424 AbstractFieldElement originalField = originalElement; | 425 AbstractFieldElement originalField = originalElement; |
| 425 if (patchField.getter !== null) { | 426 if (patchField.getter !== null) { |
| 426 if (originalField === null || originalField.getter === null) { | 427 if (originalField === null || originalField.getter === null) { |
| 427 original.addGetterOrSetter(clonePatch(patchField.getter, original), | 428 original.addGetterOrSetter(clonePatch(patchField.getter, original), |
| 428 originalField, | 429 originalField, |
| 429 this); | 430 this); |
| 430 if (originalField === null && patchField.setter !== null) { | 431 if (originalField === null && patchField.setter !== null) { |
| 431 // It exists now, so find it for the setter patching. | 432 // It exists now, so find it for the setter patching. |
| 432 originalField = lookup(patchElement.name); | 433 originalField = original.localLookup(patchElement.name); |
| 433 } | 434 } |
| 434 } else { | 435 } else { |
| 435 patchMember(originalField.getter, patchField.getter); | 436 patchMember(originalField.getter, patchField.getter); |
| 436 } | 437 } |
| 437 } | 438 } |
| 438 if (patchField.setter !== null) { | 439 if (patchField.setter !== null) { |
| 439 if (originalField === null || originalField.setter === null) { | 440 if (originalField === null || originalField.setter === null) { |
| 440 original.addGetterOrSetter(clonePatch(patchField.setter, original), | 441 original.addGetterOrSetter(clonePatch(patchField.setter, original), |
| 441 originalField, | 442 originalField, |
| 442 this); | 443 this); |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 534 } | 535 } |
| 535 | 536 |
| 536 void applyClassPatch(PartialClassElement original, | 537 void applyClassPatch(PartialClassElement original, |
| 537 PartialClassElement patch) { | 538 PartialClassElement patch) { |
| 538 // Eagerly parse the class so we can patch it. | 539 // Eagerly parse the class so we can patch it. |
| 539 // TODO(lrn): Perhaps find a way to delay parsing until the class is needed, | 540 // TODO(lrn): Perhaps find a way to delay parsing until the class is needed, |
| 540 // i.e., until [parseNode] is called on [original]. | 541 // i.e., until [parseNode] is called on [original]. |
| 541 ClassNode node = original.parseNode(this); | 542 ClassNode node = original.parseNode(this); |
| 542 // Parse patch class with "patch" parser. | 543 // Parse patch class with "patch" parser. |
| 543 ClassNode patchNode = patchParser.parsePatchClassNode(patch); | 544 ClassNode patchNode = patchParser.parsePatchClassNode(patch); |
| 544 Link<Element> patches = patch.members; | 545 Link<Element> patches = patch.localMembers; |
| 545 Element lookupMemberOrConstructor(SourceString name) { | 546 applyContainerPatch(original, patches); |
| 546 Element result = original.lookupLocalMember(name); | |
| 547 if (result !== null) return result; | |
| 548 return original.lookupConstructor(name); | |
| 549 } | |
| 550 applyContainerPatch(original, patches, lookupMemberOrConstructor); | |
| 551 } | 547 } |
| 552 | 548 |
| 553 /** | 549 /** |
| 554 * Get an [Uri] pointing to a patch for the dart: library with | 550 * Get an [Uri] pointing to a patch for the dart: library with |
| 555 * the given path. Returns null if there is no patch. | 551 * the given path. Returns null if there is no patch. |
| 556 */ | 552 */ |
| 557 abstract Uri resolvePatchUri(String dartLibraryPath); | 553 abstract Uri resolvePatchUri(String dartLibraryPath); |
| 558 | 554 |
| 559 /** Define the JS helper functions in the given library. */ | 555 /** Define the JS helper functions in the given library. */ |
| 560 void addForeignFunctions(LibraryElement library) { | 556 void addForeignFunctions(LibraryElement library) { |
| 561 library.define(new ForeignElement( | 557 library.addToScope(new ForeignElement( |
| 562 const SourceString('JS'), library), this); | 558 const SourceString('JS'), library), this); |
| 563 library.define(new ForeignElement( | 559 library.addToScope(new ForeignElement( |
| 564 const SourceString('UNINTERCEPTED'), library), this); | 560 const SourceString('UNINTERCEPTED'), library), this); |
| 565 library.define(new ForeignElement( | 561 library.addToScope(new ForeignElement( |
| 566 const SourceString('JS_HAS_EQUALS'), library), this); | 562 const SourceString('JS_HAS_EQUALS'), library), this); |
| 567 library.define(new ForeignElement( | 563 library.addToScope(new ForeignElement( |
| 568 const SourceString('JS_CURRENT_ISOLATE'), library), this); | 564 const SourceString('JS_CURRENT_ISOLATE'), library), this); |
| 569 library.define(new ForeignElement( | 565 library.addToScope(new ForeignElement( |
| 570 const SourceString('JS_CALL_IN_ISOLATE'), library), this); | 566 const SourceString('JS_CALL_IN_ISOLATE'), library), this); |
| 571 library.define(new ForeignElement( | 567 library.addToScope(new ForeignElement( |
| 572 const SourceString('DART_CLOSURE_TO_JS'), library), this); | 568 const SourceString('DART_CLOSURE_TO_JS'), library), this); |
| 573 } | 569 } |
| 574 | 570 |
| 575 void runCompiler(Uri uri) { | 571 void runCompiler(Uri uri) { |
| 576 scanBuiltinLibraries(); | 572 scanBuiltinLibraries(); |
| 577 mainApp = scanner.loadLibrary(uri, null); | 573 mainApp = scanner.loadLibrary(uri, null); |
| 578 final Element main = mainApp.find(MAIN); | 574 final Element main = mainApp.find(MAIN); |
| 579 if (main === null) { | 575 if (main === null) { |
| 580 reportFatalError('Could not find $MAIN', mainApp); | 576 reportFatalError('Could not find $MAIN', mainApp); |
| 581 } else { | 577 } else { |
| (...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 946 final endOffset = end.charOffset + end.slowCharCount; | 942 final endOffset = end.charOffset + end.slowCharCount; |
| 947 | 943 |
| 948 // [begin] and [end] might be the same for the same empty token. This | 944 // [begin] and [end] might be the same for the same empty token. This |
| 949 // happens for instance when scanning '$$'. | 945 // happens for instance when scanning '$$'. |
| 950 assert(endOffset >= beginOffset); | 946 assert(endOffset >= beginOffset); |
| 951 return f(beginOffset, endOffset); | 947 return f(beginOffset, endOffset); |
| 952 } | 948 } |
| 953 | 949 |
| 954 String toString() => 'SourceSpan($uri, $begin, $end)'; | 950 String toString() => 'SourceSpan($uri, $begin, $end)'; |
| 955 } | 951 } |
| OLD | NEW |