diff --git a/BUILD.gn b/BUILD.gn index b57d63f91fde2..f1b787c3ef63e 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -7,7 +7,7 @@ import("$flutter_root/common/config.gni") # Whether to build the dartdevc sdk, libraries, and source files # required for the flutter web sdk. declare_args() { - full_dart_sdk = false + full_dart_sdk = false } group("flutter") { diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index f5259b505f734..42b501b39285b 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -748,7 +748,9 @@ FILE: ../../../flutter/vulkan/vulkan_utilities.h FILE: ../../../flutter/vulkan/vulkan_window.cc FILE: ../../../flutter/vulkan/vulkan_window.h FILE: ../../../flutter/web_sdk/flutter_kernel_sdk.dart +FILE: ../../../flutter/web_sdk/libraries.dart FILE: ../../../flutter/web_sdk/libraries.json +FILE: ../../../flutter/web_sdk/make_combined_sdk.dart ---------------------------------------------------------------------------------------------------- Copyright 2013 The Flutter Authors. All rights reserved. diff --git a/web_sdk/BUILD.gn b/web_sdk/BUILD.gn index 925f6000499b5..57f8e4296666f 100644 --- a/web_sdk/BUILD.gn +++ b/web_sdk/BUILD.gn @@ -28,8 +28,7 @@ web_ui_sources = [ group("web_sdk") { deps = [ - ":web_ui_sources", - ":web_ui_library", + ":generate_web_summary_sdk", ":flutter_dartdevc_kernel_sdk", ] } @@ -52,6 +51,31 @@ copy("web_ui_library") { ] } +prebuilt_dart_action("generate_web_summary_sdk") { + script = "$flutter_root/web_sdk/make_combined_sdk.dart" + + inputs = [ + "$flutter_root/web_sdk/make_combined_sdk.dart", + "$flutter_root/web_sdk/libraries.dart", + ] + + packages = "//third_party/dart/.packages" + + args = [] + + outputs = [ + "$root_out_dir/flutter_web_sdk/js/amd/sdk.js", + "$root_out_dir/flutter_web_sdk/js/amd/dart_sdk.js.map", + "$root_out_dir/flutter_web_sdk/lib/_internal/ddc_sdk.sum", + ] + + deps = [ + ":web_ui_sources", + ":web_ui_library", + "//third_party/dart:create_sdk", + ] +} + prebuilt_dart_action("flutter_dartdevc_kernel_sdk") { deps = [ "//third_party/dart/pkg:pkg_files_stamp", diff --git a/web_sdk/flutter_kernel_sdk.dart b/web_sdk/flutter_kernel_sdk.dart index dea21c2de8ae5..96e181977b694 100644 --- a/web_sdk/flutter_kernel_sdk.dart +++ b/web_sdk/flutter_kernel_sdk.dart @@ -6,11 +6,11 @@ import 'dart:async'; import 'dart:convert' show json; import 'dart:io'; import 'package:args/args.dart' show ArgParser; -import 'package:dev_compiler/src/compiler/module_builder.dart'; -import 'package:dev_compiler/src/compiler/shared_command.dart' show SharedCompilerOptions; -import 'package:dev_compiler/src/kernel/target.dart'; -import 'package:dev_compiler/src/kernel/command.dart'; -import 'package:dev_compiler/src/kernel/compiler.dart'; +import 'package:dev_compiler/src/compiler/module_builder.dart'; // ignore: uri_does_not_exist +import 'package:dev_compiler/src/compiler/shared_command.dart' show SharedCompilerOptions; // ignore: uri_does_not_exist +import 'package:dev_compiler/src/kernel/target.dart'; // ignore: uri_does_not_exist +import 'package:dev_compiler/src/kernel/command.dart'; // ignore: uri_does_not_exist +import 'package:dev_compiler/src/kernel/compiler.dart'; // ignore: uri_does_not_exist import 'package:front_end/src/api_unstable/ddc.dart' show CompilerOptions, kernelForComponent; import 'package:kernel/kernel.dart'; import 'package:path/path.dart' as path; diff --git a/web_sdk/libraries.dart b/web_sdk/libraries.dart new file mode 100644 index 0000000000000..318bedf092f57 --- /dev/null +++ b/web_sdk/libraries.dart @@ -0,0 +1,313 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +library libraries; + +// Branched from https://github.com/dart-lang/sdk/blob/master/pkg/dev_compiler/tool/input_sdk/libraries.dart +// with handling for dart:ui added. + +/** + * A bit flag used by [LibraryInfo] indicating that a library is used by dart2js + */ +const int DART2JS_PLATFORM = 1; + +/** + * A bit flag used by [LibraryInfo] indicating that a library is used by the VM + */ +const int VM_PLATFORM = 2; + +/// The contexts that a library can be used from. +enum Category { + /// Indicates that a library can be used in a browser context. + client, + + /// Indicates that a library can be used in a command line context. + server, + + /// Indicates that a library can be used from embedded devices. + embedded +} + +Category parseCategory(String name) { + switch (name) { + case "Client": + return Category.client; + case "Server": + return Category.server; + case "Embedded": + return Category.embedded; + } + return null; +} + +/// Mapping of "dart:" library name (e.g. "core") to information about that +/// library. +const Map libraries = const { + "async": const LibraryInfo("async/async.dart", + categories: "Client,Server", + maturity: Maturity.STABLE, + dart2jsPatchPath: "_internal/js_runtime/lib/async_patch.dart"), + "collection": const LibraryInfo("collection/collection.dart", + categories: "Client,Server,Embedded", + maturity: Maturity.STABLE, + dart2jsPatchPath: "_internal/js_runtime/lib/collection_patch.dart"), + "convert": const LibraryInfo("convert/convert.dart", + categories: "Client,Server", + maturity: Maturity.STABLE, + dart2jsPatchPath: "_internal/js_runtime/lib/convert_patch.dart"), + "core": const LibraryInfo("core/core.dart", + categories: "Client,Server,Embedded", + maturity: Maturity.STABLE, + dart2jsPatchPath: "_internal/js_runtime/lib/core_patch.dart"), + "developer": const LibraryInfo("developer/developer.dart", + categories: "Client,Server,Embedded", + maturity: Maturity.UNSTABLE, + dart2jsPatchPath: "_internal/js_runtime/lib/developer_patch.dart"), + "html": const LibraryInfo("html/dart2js/html_dart2js.dart", + categories: "Client", + maturity: Maturity.WEB_STABLE, + platforms: DART2JS_PLATFORM), + "html_common": const LibraryInfo("html/html_common/html_common.dart", + categories: "Client", + maturity: Maturity.WEB_STABLE, + dart2jsPath: "html/html_common/html_common_dart2js.dart", + documented: false, + implementation: true), + "indexed_db": const LibraryInfo("indexed_db/dart2js/indexed_db_dart2js.dart", + categories: "Client", + maturity: Maturity.WEB_STABLE, + platforms: DART2JS_PLATFORM), + "_http": + const LibraryInfo("_http/http.dart", categories: "", documented: false), + "io": const LibraryInfo("io/io.dart", + categories: "Server", + dart2jsPatchPath: "_internal/js_runtime/lib/io_patch.dart"), + "isolate": const LibraryInfo("isolate/isolate.dart", + categories: "Client,Server", + maturity: Maturity.STABLE, + dart2jsPatchPath: "_internal/js_runtime/lib/isolate_patch.dart"), + "js": const LibraryInfo("js/dart2js/js_dart2js.dart", + categories: "Client", + maturity: Maturity.STABLE, + platforms: DART2JS_PLATFORM), + "js_util": const LibraryInfo("js_util/dart2js/js_util_dart2js.dart", + categories: "Client", + maturity: Maturity.STABLE, + platforms: DART2JS_PLATFORM), + "math": const LibraryInfo("math/math.dart", + categories: "Client,Server,Embedded", + maturity: Maturity.STABLE, + dart2jsPatchPath: "_internal/js_runtime/lib/math_patch.dart"), + "mirrors": const LibraryInfo("mirrors/mirrors.dart", + categories: "Client,Server", + maturity: Maturity.UNSTABLE, + dart2jsPatchPath: "_internal/js_runtime/lib/mirrors_patch.dart"), + "nativewrappers": const LibraryInfo("html/dartium/nativewrappers.dart", + categories: "Client", + implementation: true, + documented: false, + platforms: DART2JS_PLATFORM), + "typed_data": const LibraryInfo("typed_data/typed_data.dart", + categories: "Client,Server,Embedded", + maturity: Maturity.STABLE, + dart2jsPatchPath: "_internal/js_runtime/lib/typed_data_patch.dart"), + "_native_typed_data": const LibraryInfo( + "_internal/js_runtime/lib/native_typed_data.dart", + categories: "", + implementation: true, + documented: false, + platforms: DART2JS_PLATFORM), + "cli": const LibraryInfo("cli/cli.dart", + categories: "Server", + dart2jsPatchPath: "_internal/js_runtime/lib/cli_patch.dart"), + "svg": const LibraryInfo("svg/dart2js/svg_dart2js.dart", + categories: "Client", + maturity: Maturity.WEB_STABLE, + platforms: DART2JS_PLATFORM), + "web_audio": const LibraryInfo("web_audio/dart2js/web_audio_dart2js.dart", + categories: "Client", + maturity: Maturity.WEB_STABLE, + platforms: DART2JS_PLATFORM), + "web_gl": const LibraryInfo("web_gl/dart2js/web_gl_dart2js.dart", + categories: "Client", + maturity: Maturity.WEB_STABLE, + platforms: DART2JS_PLATFORM), + "web_sql": const LibraryInfo("web_sql/dart2js/web_sql_dart2js.dart", + categories: "Client", + maturity: Maturity.WEB_STABLE, + platforms: DART2JS_PLATFORM), + "_internal": const LibraryInfo("internal/internal.dart", + categories: "", + documented: false, + dart2jsPatchPath: "_internal/js_runtime/lib/internal_patch.dart"), + "_js_helper": const LibraryInfo("_internal/js_runtime/lib/js_helper.dart", + categories: "", documented: false, platforms: DART2JS_PLATFORM), + "_interceptors": const LibraryInfo( + "_internal/js_runtime/lib/interceptors.dart", + categories: "", + documented: false, + platforms: DART2JS_PLATFORM), + "_foreign_helper": const LibraryInfo( + "_internal/js_runtime/lib/foreign_helper.dart", + categories: "", + documented: false, + platforms: DART2JS_PLATFORM), + "_isolate_helper": const LibraryInfo( + "_internal/js_runtime/lib/isolate_helper.dart", + categories: "", + documented: false, + platforms: DART2JS_PLATFORM), + "_js_mirrors": const LibraryInfo("_internal/js_runtime/lib/js_mirrors.dart", + categories: "", documented: false, platforms: DART2JS_PLATFORM), + "_js_primitives": const LibraryInfo( + "_internal/js_runtime/lib/js_primitives.dart", + categories: "", + documented: false, + platforms: DART2JS_PLATFORM), + "_metadata": const LibraryInfo("html/html_common/metadata.dart", + categories: "", documented: false, platforms: DART2JS_PLATFORM), + "_debugger": const LibraryInfo("_internal/js_runtime/lib/debugger.dart", + category: "", documented: false, platforms: DART2JS_PLATFORM), + "_runtime": const LibraryInfo( + "_internal/js_runtime/lib/ddc_runtime/runtime.dart", + category: "", + documented: false, + platforms: DART2JS_PLATFORM), + "ui": const LibraryInfo("ui/ui.dart", documented: true, platforms:DART2JS_PLATFORM), +}; + +/** + * Information about a "dart:" library. + */ +class LibraryInfo { + /** + * Path to the library's *.dart file relative to this file. + */ + final String path; + + /** + * The categories in which the library can be used encoded as a + * comma-separated String. + */ + final String _categories; + + /** + * Path to the dart2js library's *.dart file relative to this file + * or null if dart2js uses the common library path defined above. + * Access using the [#getDart2JsPath()] method. + */ + final String dart2jsPath; + + /** + * Path to the dart2js library's patch file relative to this file + * or null if no dart2js patch file associated with this library. + * Access using the [#getDart2JsPatchPath()] method. + */ + final String dart2jsPatchPath; + + /** + * True if this library is documented and should be shown to the user. + */ + final bool documented; + + /** + * Bit flags indicating which platforms consume this library. + * See [DART2JS_LIBRARY] and [VM_LIBRARY]. + */ + final int platforms; + + /** + * True if the library contains implementation details for another library. + * The implication is that these libraries are less commonly used + * and that tools like Dart Editor should not show these libraries + * in a list of all libraries unless the user specifically asks the tool to + * do so. + */ + final bool implementation; + + /** + * States the current maturity of this library. + */ + final Maturity maturity; + + const LibraryInfo(this.path, + {String categories: "", + this.dart2jsPath, + this.dart2jsPatchPath, + this.implementation: false, + this.documented: true, + this.maturity: Maturity.UNSPECIFIED, + this.platforms: DART2JS_PLATFORM | VM_PLATFORM}) + : _categories = categories; + + bool get isDart2jsLibrary => (platforms & DART2JS_PLATFORM) != 0; + bool get isVmLibrary => (platforms & VM_PLATFORM) != 0; + + /** + * The categories in which the library can be used. + * + * If no categories are specified, the library is internal and can not be + * loaded by user code. + */ + List get categories { + // `"".split(,)` returns [""] not [], so we handle that case separately. + if (_categories == "") return const []; + return _categories.split(",").map(parseCategory).toList(); + } + + bool get isInternal => categories.isEmpty; + + /// The original "categories" String that was passed to the constructor. + /// + /// Can be used to construct a slightly modified copy of this LibraryInfo. + String get categoriesString { + return _categories; + } +} + +/** + * Abstraction to capture the maturity of a library. + */ +class Maturity { + final int level; + final String name; + final String description; + + const Maturity(this.level, this.name, this.description); + + String toString() => "$name: $level\n$description\n"; + + static const Maturity DEPRECATED = const Maturity(0, "Deprecated", + "This library will be remove before next major release."); + + static const Maturity EXPERIMENTAL = const Maturity( + 1, + "Experimental", + "This library is experimental and will likely change or be removed\n" + "in future versions."); + + static const Maturity UNSTABLE = const Maturity( + 2, + "Unstable", + "This library is in still changing and have not yet endured\n" + "sufficient real-world testing.\n" + "Backwards-compatibility is NOT guaranteed."); + + static const Maturity WEB_STABLE = const Maturity( + 3, + "Web Stable", + "This library is tracking the DOM evolution as defined by WC3.\n" + "Backwards-compatibility is NOT guaranteed."); + + static const Maturity STABLE = const Maturity( + 4, + "Stable", + "The library is stable. API backwards-compatibility is guaranteed.\n" + "However implementation details might change."); + + static const Maturity LOCKED = const Maturity(5, "Locked", + "This library will not change except when serious bugs are encountered."); + + static const Maturity UNSPECIFIED = const Maturity(-1, "Unspecified", + "The maturity for this library has not been specified."); +} diff --git a/web_sdk/make_combined_sdk.dart b/web_sdk/make_combined_sdk.dart new file mode 100755 index 0000000000000..435fb22174424 --- /dev/null +++ b/web_sdk/make_combined_sdk.dart @@ -0,0 +1,120 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:io'; + +import 'package:path/path.dart' as path; +import 'package:dev_compiler/src/analyzer/command.dart' as command; // ignore: uri_does_not_exist + +// Creates flutter precompiled web sdk and analyzer summary. +Future main() async { + // create a temporary dart-sdk directory. + final Directory tempDartSdk = Directory(path.join('temp_dart_sdk', 'lib')) + ..createSync(recursive: true); + final Directory patchedDartSdk = Directory(path.join( + 'gen', 'third_party', 'dart', 'utils', 'dartdevc', 'patched_sdk', 'lib')); + final Directory flutterWebUi = Directory(path.join( + 'flutter_web_sdk', + 'lib', + 'ui', + )); + + // Copy this patched dart sdk into the temporary directory. + for (FileSystemEntity entity in patchedDartSdk.listSync(recursive: true)) { + if (entity is File) { + final String targetPath = path.join(tempDartSdk.path, + path.relative(entity.path, from: patchedDartSdk.path)); + File(targetPath).createSync(recursive: true); + entity.copySync(path.join(tempDartSdk.path, + path.relative(entity.path, from: patchedDartSdk.path))); + } + } + // Copy the dart:ui sources into the temporary directory. + for (FileSystemEntity entity in flutterWebUi.listSync(recursive: true)) { + if (entity is File) { + final String targetPath = path.join(tempDartSdk.path, 'ui', + path.relative(entity.path, from: flutterWebUi.path)); + File(targetPath).createSync(recursive: true); + entity.copySync(targetPath); + } + } + // Copy the libraries.dart file into the temporary directory. + final File libraries = File(path.join('..', '..', 'flutter', 'web_sdk', 'libraries.dart')); + libraries.copySync(path.join(tempDartSdk.path, '_internal', 'libraries.dart')); + libraries.copySync(path.join(tempDartSdk.path, '_internal', 'sdk_library_metadata', 'lib', 'libraries.dart')); + + // Prevent regular compilation from leaking into flutter + final File ddcSummary = + File(path.join(tempDartSdk.path, '_internal', 'ddc_sdk.sum')); + final File jsSdk = + File(path.join(tempDartSdk.parent.path, 'js', 'amd', 'dart_sdk.js')); + final File jsSdkMap = + File(path.join(tempDartSdk.parent.path, 'js', 'amd', 'dart_sdk.js.map')); + if (ddcSummary.existsSync()) { + ddcSummary.deleteSync(); + } + if (jsSdk.existsSync()) { + jsSdk.deleteSync(); + } + if (jsSdkMap.existsSync()) { + jsSdkMap.deleteSync(); + } + + // Execute the analyzer summary and sdk generation. + final List args = ['--no-source-map', '--no-emit-metadata']; + args.addAll([ + '--dart-sdk=temp_dart_sdk', + '--dart-sdk-summary=build', + '--summary-out=temp_dart_sdk/lib/_internal/ddc_sdk.sum', + '--source-map', + '--source-map-comment', + '--modules=amd', + '-o', + 'temp_dart_sdk/js/amd/dart_sdk.js' + ]); + args.addAll([ + 'dart:_runtime', + 'dart:_debugger', + 'dart:_foreign_helper', + 'dart:_interceptors', + 'dart:_internal', + 'dart:_isolate_helper', + 'dart:_js_helper', + 'dart:_js_mirrors', + 'dart:_js_primitives', + 'dart:_metadata', + 'dart:_native_typed_data', + 'dart:async', + 'dart:collection', + 'dart:convert', + 'dart:core', + 'dart:developer', + 'dart:io', + 'dart:isolate', + 'dart:js', + 'dart:js_util', + 'dart:math', + 'dart:mirrors', + 'dart:typed_data', + 'dart:indexed_db', + 'dart:html', + 'dart:html_common', + 'dart:svg', + 'dart:web_audio', + 'dart:web_gl', + 'dart:web_sql', + 'dart:ui', + ]); + final int result = (await command.compile(args)).exitCode; + if (result != 0) { + throw 'SDK generation failed with exit code $result'; + } + + // Copy generated sdk and summary back to flutter web sdk. + ddcSummary.copySync( + path.join('flutter_web_sdk', 'lib', '_internal', 'ddc_sdk.sum')); + jsSdk.copySync(path.join('flutter_web_sdk', 'js', 'amd', 'dart_sdk.js')); + jsSdkMap + .copySync(path.join('flutter_web_sdk', 'js', 'amd', 'dart_sdk.js.map')); +} diff --git a/web_sdk/make_combined_sdk.sh b/web_sdk/make_combined_sdk.sh deleted file mode 100755 index 06b673baba8a2..0000000000000 --- a/web_sdk/make_combined_sdk.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -# Reference script for creating patched sdk locally. -# Copy normal dart sources into flutter_patched sdk -mkdir -p out/host_debug_unopt/flutter_patched_sdk/lib -cp -RL out/host_debug_unopt/dart-sdk/lib/ out/host_debug_unopt/flutter_patched_sdk/lib - -# Copy stub ui dart sources into flutter_patched sdk -mkdir -p out/host_debug_unopt/flutter_patched_sdk/lib/ui -cp -RL flutter/lib/stub_ui/ out/host_debug_unopt/flutter_patched_sdk/lib/ui - -# Copy libraries.json into flutter patched sdk. -cp -RL flutter/flutter_web/libraries.json out/host_debug_unopt/flutter_patched_sdk/lib/libraries.json - -# Copy libraries.dart into flutter patched sdk -cp -RL flutter/flutter_web/libraries.dart out/host_debug_unopt/flutter_patched_sdk/lib/_internal/libraries.dart