| 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 76%
|
| copy from pkg/dev_compiler/tool/patch_sdk.dart
|
| copy to tools/patch_sdk.dart
|
| index 3c7e543112252d828b45ed7f3ce3f16adfb395ff..ca547cda6f7f20ee34bf097496d1eef0aa648799
|
| --- a/pkg/dev_compiler/tool/patch_sdk.dart
|
| +++ b/tools/patch_sdk.dart
|
| @@ -14,38 +14,55 @@ 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);
|
| + var libContents = new File(path.join(sdkLibIn, '_internal',
|
| + 'sdk_library_metadata', 'lib', 'libraries.dart')).readAsStringSync();
|
| _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 +71,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 +145,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.toString(), 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 [['nativewrappers', 'nativewrappers.dart'],
|
| + ['_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 +216,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 +339,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 +389,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);
|
|
|