Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions dwds/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 26.2.4-wip

- Updating bootstrapper for DDC library bundler module format.

## 26.2.3-wip

- Bump `build_web_compilers` to ^4.4.1.
Expand Down
8 changes: 0 additions & 8 deletions dwds/lib/src/loaders/ddc_library_bundle.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
// for details. 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:convert';

import 'package:dwds/src/debugging/dart_runtime_debugger.dart';
import 'package:dwds/src/debugging/metadata/provider.dart';
import 'package:dwds/src/loaders/ddc.dart';
Expand Down Expand Up @@ -197,12 +195,6 @@ class DdcLibraryBundleStrategy extends LoadStrategy {
});
return '''
$baseUrlScript
var scripts = ${const JsonEncoder.withIndent(" ").convert(scripts)};
window.\$dartLoader.loadConfig.loadScriptFn = function(loader) {
loader.addScriptsToQueue(scripts, null);
loader.loadEnqueuedModules();
};
window.\$dartLoader.loader.nextAttempt();
''';
}

Expand Down
2 changes: 1 addition & 1 deletion dwds/lib/src/version.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dwds/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: dwds
# Every time this changes you need to run `dart run build_runner build`.
version: 26.2.3-wip
version: 26.2.4-wip

description: >-
A service that proxies between the Chrome debug protocol and the Dart VM
Expand Down
4 changes: 4 additions & 0 deletions webdev/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 3.8.1-wip

- Adding initial DDC library bundler support behind the `canary` flag.

## 3.8.0-wip

- Bump minimum SDK constraint to 3.10.0
Expand Down
3 changes: 2 additions & 1 deletion webdev/lib/src/command/build_command.dart
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ class BuildCommand extends Command<int> {
DefaultBuildTarget(
(b) => b
..target = configuration.outputInput
..outputLocation = outputLocation?.toBuilder(),
..outputLocation = outputLocation?.toBuilder()
..reportChangedAssets = true,
),
);
client.startBuild();
Expand Down
18 changes: 18 additions & 0 deletions webdev/lib/src/command/shared.dart
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,24 @@ List<String> buildRunnerArgs(Configuration configuration) {
arguments.add('--enable-experiment=$experiment');
}

if (configuration.canaryFeatures) {
arguments
..add('--define')
..add('build_web_compilers|sdk_js=web-hot-reload=true');
arguments
..add('--define')
..add('build_web_compilers|entrypoint=web-hot-reload=true');
arguments
..add('--define')
..add('build_web_compilers|entrypoint_marker=web-hot-reload=true');
arguments
..add('--define')
..add('build_web_compilers|ddc=web-hot-reload=true');
arguments
..add('--define')
..add('build_web_compilers|ddc_modules=web-hot-reload=true');
}

return arguments;
}

Expand Down
6 changes: 4 additions & 2 deletions webdev/lib/src/serve/dev_workflow.dart
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,8 @@ void _registerBuildTargets(
DefaultBuildTarget(
(b) => b
..target = target
..outputLocation = outputLocation?.toBuilder(),
..outputLocation = outputLocation?.toBuilder()
..reportChangedAssets = true,
),
);
}
Expand All @@ -161,7 +162,8 @@ void _registerBuildTargets(
DefaultBuildTarget(
(b) => b
..target = ''
..outputLocation = outputLocation.toBuilder(),
..outputLocation = outputLocation.toBuilder()
..reportChangedAssets = true,
),
);
}
Expand Down
24 changes: 24 additions & 0 deletions webdev/lib/src/serve/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,27 @@ String? findPackageConfigFilePath() {
candidateDir = parentDir;
}
}

/// Returns the absolute file path of the `package_config.json` file in the `.dart_tool`
/// directory, searching recursively from the current directory hierarchy.
Uri? findPackageConfigUri() {
var candidateDir = Directory(p.current).absolute;

while (true) {
final candidatePackageConfigFile = File(
p.join(candidateDir.path, '.dart_tool', 'package_config.json'),
);

if (candidatePackageConfigFile.existsSync()) {
return candidatePackageConfigFile.uri;
}

final parentDir = candidateDir.parent;
if (parentDir.path == candidateDir.path) {
// We've reached the root directory
return null;
}

candidateDir = parentDir;
}
}
150 changes: 141 additions & 9 deletions webdev/lib/src/serve/webdev_server.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
// BSD-style license that can be found in the LICENSE file.

import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:build_daemon/data/build_status.dart' as daemon;
import 'package:dds/devtools_server.dart';
import 'package:dwds/data/build_result.dart';
import 'package:dwds/dwds.dart';
import 'package:dwds/sdk_configuration.dart';
import 'package:file/local.dart';
import 'package:http/http.dart' as http;
import 'package:http/io_client.dart';
import 'package:http_multi_server/http_multi_server.dart';
Expand All @@ -21,10 +23,14 @@ import '../command/configuration.dart';
import '../util.dart';
import 'chrome.dart';
import 'handlers/favicon_handler.dart';
import 'utils.dart' show findPackageConfigFilePath;
import 'utils.dart' show findPackageConfigFilePath, findPackageConfigUri;

Logger _logger = Logger('WebDevServer');

const reloadedSourcesFileName = 'reloaded_sources.json';
const jsLibraryBundleExtension = '.ddc.js';
const multiRootScheme = 'org-dartlang-app';

class ServerOptions {
final Configuration configuration;
final int port;
Expand Down Expand Up @@ -80,6 +86,7 @@ class WebDevServer {
ServerOptions options,
Stream<daemon.BuildResults> buildResults,
) async {
final basePath = 'http://localhost:${options.port}';
var pipeline = const Pipeline();

if (options.configuration.logRequests) {
Expand All @@ -88,8 +95,47 @@ class WebDevServer {

pipeline = pipeline.addMiddleware(interceptFavicon);

/// JSON-ifiable list of sources that were reloaded in this restart and
/// follows the following format:
///
/// `src`: A string that corresponds to the file path containing a DDC library
/// bundle. To support embedded libraries, the path should include the
/// `baseUri` of the web server.
/// `module`: The name of the library bundle in `src`.
/// `libraries`: An array of strings containing the libraries that were
/// compiled in `src`.
///
/// For example:
/// ```json
/// [
/// {
/// "src": "<baseUri>/<file_name>",
/// "module": "<module_name>",
/// "libraries": ["<lib1>", "<lib2>"],
/// },
/// ]
/// ```
///
/// The path of the output file should stay consistent across the lifetime of
/// the app.
final reloadedSources = <Map<String, dynamic>>[];

// Only provide relevant build results
final filteredBuildResults = buildResults.asyncMap<BuildResult>((results) {
if (options.configuration.canaryFeatures) {
// Clear reloaded sources for the new build results.
reloadedSources.clear();
results.changedAssets?.forEach((uri) {
if (uri.path.endsWith(jsLibraryBundleExtension)) {
final reloadedSource = {
'src': ddcUriToSourceUrl(basePath, options.target, uri),
'module': ddcUriToLibraryId(uri),
'libraries': [ddcUriToLibraryId(uri)],
};
reloadedSources.add(reloadedSource);
}
});
}
final result = results.results.firstWhere(
(result) => result.target == options.target,
);
Expand Down Expand Up @@ -132,20 +178,39 @@ class WebDevServer {
// the load strategy?
final buildSettings = BuildSettings(
appEntrypoint: Uri.parse(
'org-dartlang-app:///${options.target}/main.dart',
'$multiRootScheme:///${options.target}/main.dart',
),
canaryFeatures: options.configuration.canaryFeatures,
isFlutterApp: false,
experiments: options.configuration.experiments,
);

final loadStrategy = BuildRunnerRequireStrategyProvider(
assetHandler,
options.configuration.reload,
assetReader,
buildSettings,
packageConfigPath: findPackageConfigFilePath(),
).strategy;
final LoadStrategy loadStrategy;
if (options.configuration.canaryFeatures) {
final frontendServerFileSystem = LocalFileSystem();
final packageUriMapper = await PackageUriMapper.create(
frontendServerFileSystem,
findPackageConfigUri()!,
useDebuggerModuleNames: false,
);
loadStrategy = FrontendServerDdcLibraryBundleStrategyProvider(
options.configuration.reload,
assetReader,
packageUriMapper,
() async => {},
buildSettings,
packageConfigPath: findPackageConfigFilePath(),
reloadedSourcesUri: Uri.parse('$basePath/$reloadedSourcesFileName'),
).strategy;
} else {
loadStrategy = BuildRunnerRequireStrategyProvider(
assetHandler,
options.configuration.reload,
assetReader,
buildSettings,
packageConfigPath: findPackageConfigFilePath(),
).strategy;
}

if (options.configuration.enableExpressionEvaluation) {
ddcService = ExpressionCompilerService(
Expand Down Expand Up @@ -191,6 +256,18 @@ class WebDevServer {
);
pipeline = pipeline.addMiddleware(dwds.middleware);
cascade = cascade.add(dwds.handler);
if (options.configuration.canaryFeatures) {
// Add a handler to serve reloaded sources.
cascade = cascade.add((Request request) {
if (request.url.path == reloadedSourcesFileName) {
return Response.ok(
jsonEncode(reloadedSources),
headers: {'Content-Type': 'application/json'},
);
}
return Response.notFound('');
});
}
cascade = cascade.add(assetHandler);
} else {
cascade = cascade.add(assetHandler);
Expand Down Expand Up @@ -233,3 +310,58 @@ class WebDevServer {
);
}
}

/// Transforms a package:build JS asset id [uri] into a source url compatible
/// with DDC's bootstrapper.
///
/// [basePath] is the path from which JS files as served up to but not
/// including the path.
/// [target] is the path whose files will be served from [basePath].
/// [uri] is the asset id's uri being transformed.
///
/// Example:
/// basePath: http://localhost:8080
/// target: web
///
/// uri: asset:some_package/web/main.ddc.js
/// returns http://localhost:8080/main.ddc.js
///
/// uri: package:some_package/src/sub_dir/file.ddc.js
/// returns http://localhost:8080/some_package/src/sub_dir/file.ddc.js
String ddcUriToSourceUrl(String basePath, String target, Uri uri) {
String jsPath;
if (uri.isScheme('asset')) {
// This indicates that this asset is the 'main' web asset. We directly
// serve all files under the package's [target] directory.
var pathParts = uri.pathSegments.skip(1);
if (pathParts.first == target) {
pathParts = pathParts.skip(1);
}
jsPath = pathParts.join('/');
} else if (uri.isScheme('package')) {
jsPath = 'packages/${uri.path}';
} else {
jsPath = uri.path;
}
return '$basePath/$jsPath';
}

/// Transforms a package:build JS asset id [uri] into a library id compatible
/// with DDC's bootstrapper.
///
/// Example:
/// uri: asset:some_package/web/main.ddc.js
/// returns org-dartlang-app:///web/main.dart
///
/// uri: package:some_package/src/sub_dir/file.ddc.js
/// returns package:some_package/src/sub_dir/file.dart
String ddcUriToLibraryId(Uri uri) {
final jsPath = uri.isScheme('package')
? 'package:${uri.path}'
: '$multiRootScheme:///${uri.path}';
final prefix = jsPath.substring(
0,
jsPath.length - jsLibraryBundleExtension.length,
);
return '$prefix.dart';
}
2 changes: 1 addition & 1 deletion webdev/lib/src/version.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 16 additions & 1 deletion webdev/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: webdev
# Every time this changes you need to run `dart run build_runner build`.
version: 3.8.0-wip
version: 3.8.1-wip
# We should not depend on a dev SDK before publishing.
# publish_to: none
description: >-
Expand All @@ -20,6 +20,7 @@ dependencies:
dds: ^4.1.0
# Pin DWDS to avoid dependency conflicts with vm_service:
dwds: 24.3.11
file: ^7.0.1
http: ^1.0.0
http_multi_server: ^3.2.0
io: ^1.0.3
Expand Down Expand Up @@ -53,5 +54,19 @@ dev_dependencies:
test_process: ^2.0.2
webdriver: ^3.0.0

dependency_overrides:
build_web_compilers:
path: /Users/markzipan/Projects/build/build_web_compilers
build_runner:
path: /Users/markzipan/Projects/build/build_runner
build_modules:
path: /Users/markzipan/Projects/build/build_modules
build:
path: /Users/markzipan/Projects/build/build
scratch_space:
path: /Users/markzipan/Projects/build/scratch_space
dwds:
path: /Users/markzipan/Projects/webdev/dwds

executables:
webdev:
Loading