| Index: tools/patch_sdk.dart
 | 
| diff --git a/tools/patch_sdk.dart b/tools/patch_sdk.dart
 | 
| index 81f239f3e29f06f156817f5f45b474181d21c54f..8e86120e9c5a7e37327dc2c5850a840f4c7adccf 100644
 | 
| --- a/tools/patch_sdk.dart
 | 
| +++ b/tools/patch_sdk.dart
 | 
| @@ -597,8 +597,9 @@ class PatchApplier extends GeneralizingAstVisitor {
 | 
|      var name = _qualifiedName(node);
 | 
|      var patchNode = patch.patches[name];
 | 
|      if (patchNode == null) {
 | 
| -      if (externalKeyword != null) {
 | 
| +      if (externalKeyword != null && _shouldHaveImplementation(name)) {
 | 
|          print('warning: patch not found for $name: $node');
 | 
| +        exitCode = 1;
 | 
|        }
 | 
|        return;
 | 
|      }
 | 
| @@ -615,6 +616,23 @@ class PatchApplier extends GeneralizingAstVisitor {
 | 
|    }
 | 
|  }
 | 
|  
 | 
| +/// Whether a member should have an implementation after patching the SDK.
 | 
| +///
 | 
| +/// True for most members except for the *.fromEnvironment constructors under
 | 
| +/// the dart2js target.
 | 
| +bool _shouldHaveImplementation(String qualifiedName) {
 | 
| +  if (!forDart2js) return true;
 | 
| +  // Note: dart2js implements int.fromEnvironment, bool.fromEnvironment
 | 
| +  // and String.fromEnvironment directly and expects the SDK code to
 | 
| +  // have an external declaration.
 | 
| +  var isFromEnvironment = const [
 | 
| +    'bool.fromEnvironment',
 | 
| +    'int.fromEnvironment',
 | 
| +    'String.fromEnvironment'
 | 
| +  ].contains(qualifiedName);
 | 
| +  return !isFromEnvironment;
 | 
| +}
 | 
| +
 | 
|  class PatchFinder extends GeneralizingAstVisitor {
 | 
|    final String contents;
 | 
|    final CompilationUnit unit;
 | 
| 
 |