Index: tools/patch_sdk.dart |
diff --git a/pkg/dev_compiler/tool/patch_sdk.dart b/tools/patch_sdk.dart |
old mode 100755 |
new mode 100644 |
similarity index 73% |
copy from pkg/dev_compiler/tool/patch_sdk.dart |
copy to tools/patch_sdk.dart |
index 3c7e543112252d828b45ed7f3ce3f16adfb395ff..3bb9965ec32def7758b8f5d176f55a70256b496f |
--- a/pkg/dev_compiler/tool/patch_sdk.dart |
+++ b/tools/patch_sdk.dart |
@@ -14,38 +14,87 @@ import 'package:analyzer/src/generated/sdk.dart'; |
import 'package:path/path.dart' as path; |
void main(List<String> argv) { |
- if (argv.length < 2) { |
- var self = path.relative(path.fromUri(Platform.script)); |
- var toolDir = path.relative(path.dirname(path.fromUri(Platform.script))); |
- |
- var inputExample = path.join(toolDir, 'input_sdk'); |
+ var base = path.fromUri(Platform.script); |
+ var dartDir = path.dirname(path.dirname(path.absolute(base))); |
+ |
+ if (argv.length != 4 || |
+ !argv.isEmpty && argv.first != 'vm' && argv.first != 'ddc') { |
+ var self = path.relative(base); |
+ print('Usage: $self MODE SDK_DIR PATCH_DIR OUTPUT_DIR'); |
+ print('MODE must be one of ddc or vm.'); |
+ |
+ var toolDir = path.relative(path.dirname(base)); |
+ var sdkExample = path.join(toolDir, 'input_sdk'); |
+ var patchExample = path.join(sdkExample, 'patch'); |
var outExample = |
path.relative(path.normalize(path.join('gen', 'patched_sdk'))); |
- |
- print('Usage: $self INPUT_DIR OUTPUT_DIR'); |
print('For example:'); |
- print('\$ $self $inputExample $outExample'); |
+ print('\$ $self ddc $sdkExample $patchExample $outExample'); |
+ |
+ var repositoryDir = path.relative(path.dirname(path.dirname(base))); |
+ sdkExample = path.relative(path.join(repositoryDir, 'sdk')); |
+ patchExample = path.relative(path.join(repositoryDir, 'out', 'DebugX64', |
+ 'obj', 'gen', 'patch')); |
+ outExample = path.relative(path.join(repositoryDir, 'out', 'DebugX64', |
+ 'obj', 'gen', 'patched_sdk')); |
+ print('or:'); |
+ print('\$ $self vm $sdkExample $patchExample $outExample'); |
+ |
exit(1); |
} |
- var input = argv[0]; |
+ var mode = argv[0]; |
+ var input = argv[1]; |
var sdkLibIn = path.join(input, 'lib'); |
- var patchIn = path.join(input, 'patch'); |
- var privateIn = path.join(input, 'private'); |
- var sdkOut = path.join(argv[1], 'lib'); |
+ var patchIn = argv[2]; |
+ var sdkOut = path.join(argv[3], 'lib'); |
+ var privateIn = path.join(input, 'private'); |
var INTERNAL_PATH = '_internal/compiler/js_lib/'; |
- // Copy libraries.dart and version |
- var libContents = new File(path.join(sdkLibIn, '_internal', 'libraries.dart')) |
- .readAsStringSync(); |
- _writeSync(path.join(sdkOut, '_internal', 'libraries.dart'), libContents); |
+ // Copy and patch libraries.dart and version |
+ var libContents = new File(path.join(sdkLibIn, '_internal', |
+ 'sdk_library_metadata', 'lib', 'libraries.dart')).readAsStringSync(); |
+ var patchedLibContents = libContents; |
+ if (mode == 'vm') { |
+ libContents = libContents.replaceAll( |
+ ' libraries = const {', |
+ ''' libraries = const { |
+ |
+ "_builtin": const LibraryInfo( |
+ "_builtin/_builtin.dart", |
+ categories: "Client,Server", |
+ implementation: true, |
+ documented: false, |
+ platforms: VM_PLATFORM), |
+ |
+ "profiler": const LibraryInfo( |
+ "profiler/profiler.dart", |
+ maturity: Maturity.DEPRECATED, |
+ documented: false), |
+ |
+ "_vmservice": const LibraryInfo( |
+ "vmservice/vmservice.dart", |
+ implementation: true, |
+ documented: false, |
+ platforms: VM_PLATFORM), |
+ |
+ "vmservice_io": const LibraryInfo( |
+ "vmservice_io/vmservice_io.dart", |
+ implementation: true, |
+ documented: false, |
+ platforms: VM_PLATFORM), |
+ |
+'''); |
+ } |
_writeSync( |
path.join( |
sdkOut, '_internal', 'sdk_library_metadata', 'lib', 'libraries.dart'), |
libContents); |
- _writeSync(path.join(sdkOut, '..', 'version'), |
- new File(path.join(sdkLibIn, '..', 'version')).readAsStringSync()); |
+ if (mode == 'ddc') { |
+ _writeSync(path.join(sdkOut, '..', 'version'), |
+ new File(path.join(sdkLibIn, '..', 'version')).readAsStringSync()); |
+ } |
// Parse libraries.dart |
var sdkLibraries = _getSdkLibraries(libContents); |
@@ -54,12 +103,21 @@ void main(List<String> argv) { |
for (SdkLibrary library in sdkLibraries) { |
// TODO(jmesserly): analyzer does not handle the default case of |
// "both platforms" correctly, and treats it as being supported on neither. |
- // So instead we skip explicitly marked as VM libs. |
- if (library.isVmLibrary) continue; |
+ // So instead we skip explicitly marked as either VM or dart2js libs. |
+ if (mode == 'ddc' ? libary.isVmLibrary : library.isDart2JsLibrary) { |
+ continue; |
+ } |
var libraryOut = path.join(sdkLibIn, library.path); |
var libraryIn; |
- if (library.path.contains(INTERNAL_PATH)) { |
+ if (mode == 'vm' && library.path.contains('typed_data.dart')) { |
+ // dart:typed_data is unlike the other libraries in the SDK. The VM does |
+ // not apply a patch to the base SDK implementation of the library. |
+ // Instead, the VM provides a replacement implementation and ignores the |
+ // sources in the SDK. |
+ libraryIn = |
+ path.join(dartDir, 'runtime', 'lib', 'typed_data.dart'); |
+ } else if (mode == 'ddc' && library.path.contains(INTERNAL_PATH)) { |
libraryIn = |
path.join(privateIn, library.path.replaceAll(INTERNAL_PATH, '')); |
} else { |
@@ -119,15 +177,48 @@ void main(List<String> argv) { |
contents.addAll(partFiles.map((f) => f.readAsStringSync())); |
if (patchExists) { |
var patchContents = patchFile.readAsStringSync(); |
- contents = _patchLibrary(contents, patchContents); |
+ contents = _patchLibrary( |
+ patchFile.path, contents, patchContents); |
} |
for (var i = 0; i < outPaths.length; i++) { |
+ if (path.basename(outPaths[i]) == 'internal.dart') { |
+ contents[i] += ''' |
+ |
+/// Marks a function as an external implementation ("native" in the Dart VM). |
+/// |
+/// Provides a backend-specific String that can be used to identify the |
+/// function's implementation |
+class ExternalName { |
+ final String name; |
+ const ExternalName(this.name); |
+} |
+'''; |
+ } |
+ |
_writeSync(outPaths[i], contents[i]); |
} |
} |
} |
} |
+ if (mode == 'vm') { |
+ |
+ for (var tuple in [['_builtin', 'builtin.dart']]) { |
+ var vmLibrary = tuple[0]; |
+ var dartFile = tuple[1]; |
+ |
+ // The "dart:_builtin" library is only available for the DartVM. |
+ var builtinLibraryIn = path.join(dartDir, 'runtime', 'bin', dartFile); |
+ var builtinLibraryOut = path.join(sdkOut, vmLibrary, '${vmLibrary}.dart'); |
+ _writeSync(builtinLibraryOut, new File(builtinLibraryIn).readAsStringSync()); |
+ } |
+ |
+ for (var file in ['loader.dart', 'server.dart', 'vmservice_io.dart']) { |
+ var libraryIn = path.join(dartDir, 'runtime', 'bin', 'vmservice', file); |
+ var libraryOut = path.join(sdkOut, 'vmservice_io', file); |
+ _writeSync(libraryOut, new File(libraryIn).readAsStringSync()); |
+ } |
+ } |
} |
/// Writes a file, creating the directory if needed. |
@@ -157,12 +248,14 @@ void _writeSync(String filePath, String contents) { |
/// in the Dart language. Since this feature is only for the convenience of |
/// writing the dart:* libraries, and not a tool given to Dart developers, it |
/// seems like a non-ideal situation. Instead we keep the preprocessing simple. |
-List<String> _patchLibrary(List<String> partsContents, String patchContents) { |
+List<String> _patchLibrary(String name, |
+ List<String> partsContents, |
+ String patchContents) { |
var results = <StringEditBuffer>[]; |
// Parse the patch first. We'll need to extract bits of this as we go through |
// the other files. |
- var patchFinder = new PatchFinder.parseAndVisit(patchContents); |
+ final patchFinder = new PatchFinder.parseAndVisit(name, patchContents); |
// Merge `external` declarations with the corresponding `@patch` code. |
for (var partContent in partsContents) { |
@@ -278,9 +371,9 @@ class PatchFinder extends GeneralizingAstVisitor { |
final Map mergeMembers = <String, List<ClassMember>>{}; |
final List mergeDeclarations = <CompilationUnitMember>[]; |
- PatchFinder.parseAndVisit(String contents) |
+ PatchFinder.parseAndVisit(String name, String contents) |
: contents = contents, |
- unit = parseCompilationUnit(contents) { |
+ unit = parseCompilationUnit(contents, name: name) { |
visitCompilationUnit(unit); |
} |
@@ -328,7 +421,14 @@ String _qualifiedName(Declaration node) { |
className = parent.name.name + '.'; |
} |
var name = (node as dynamic).name; |
- return className + (name != null ? name.name : ''); |
+ name = (name != null ? name.name : ''); |
+ |
+ var accessor = ''; |
+ if (node is MethodDeclaration) { |
+ if (node.isGetter) accessor = 'get:'; |
+ else if (node.isSetter) accessor = 'set:'; |
+ } |
+ return className + accessor + name; |
} |
bool _isPatch(AnnotatedNode node) => node.metadata.any(_isPatchAnnotation); |