Skip to content

Commit 8490a07

Browse files
committed
Adding support for using the Frontend Server with the Legacy/DDC module system.
1 parent 927c70e commit 8490a07

File tree

3 files changed

+196
-2
lines changed

3 files changed

+196
-2
lines changed

dwds/lib/dwds.dart

+7-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ export 'src/loaders/build_runner_require.dart'
2121
show BuildRunnerRequireStrategyProvider;
2222
export 'src/loaders/frontend_server_require.dart'
2323
show FrontendServerRequireStrategyProvider;
24+
export 'src/loaders/frontend_server_legacy.dart'
25+
show FrontendServerLegacyStrategyProvider;
2426
export 'src/loaders/legacy.dart' show LegacyStrategy;
2527
export 'src/loaders/require.dart' show RequireStrategy;
2628
export 'src/loaders/strategy.dart'
@@ -32,7 +34,11 @@ export 'src/readers/proxy_server_asset_reader.dart' show ProxyServerAssetReader;
3234
export 'src/servers/devtools.dart';
3335
export 'src/services/chrome_debug_exception.dart' show ChromeDebugException;
3436
export 'src/services/expression_compiler.dart'
35-
show ExpressionCompilationResult, ExpressionCompiler, ModuleInfo;
37+
show
38+
ExpressionCompilationResult,
39+
ExpressionCompiler,
40+
ModuleInfo,
41+
CompilerOptions;
3642
export 'src/services/expression_compiler_service.dart'
3743
show ExpressionCompilerService;
3844
export 'src/utilities/sdk_configuration.dart'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
// Copyright 2020 The Dart Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import 'package:dwds/src/debugging/metadata/provider.dart';
6+
import 'package:dwds/src/loaders/legacy.dart';
7+
import 'package:dwds/src/loaders/strategy.dart';
8+
import 'package:dwds/src/readers/asset_reader.dart';
9+
import 'package:dwds/src/services/expression_compiler.dart';
10+
import 'package:path/path.dart' as p;
11+
12+
/// Provides a [LegacyStrategy] suitable for use with Frontend Server.
13+
class FrontendServerLegacyStrategyProvider {
14+
final ReloadConfiguration _configuration;
15+
final AssetReader _assetReader;
16+
final PackageUriMapper _packageUriMapper;
17+
final Future<Map<String, String>> Function() _digestsProvider;
18+
final String _basePath;
19+
final BuildSettings _buildSettings;
20+
21+
late final LegacyStrategy _legacyStrategy = LegacyStrategy(
22+
_configuration,
23+
_moduleProvider,
24+
(_) => _digestsProvider(),
25+
_moduleForServerPath,
26+
_serverPathForModule,
27+
_sourceMapPathForModule,
28+
_serverPathForAppUri,
29+
_moduleInfoForProvider,
30+
_assetReader,
31+
_buildSettings,
32+
(String _) => null,
33+
null,
34+
);
35+
36+
FrontendServerLegacyStrategyProvider(
37+
this._configuration,
38+
this._assetReader,
39+
this._packageUriMapper,
40+
this._digestsProvider,
41+
this._buildSettings,
42+
) : _basePath = _assetReader.basePath;
43+
44+
LegacyStrategy get strategy => _legacyStrategy;
45+
46+
String _removeBasePath(String path) {
47+
if (_basePath.isEmpty) return path;
48+
49+
final stripped = stripLeadingSlashes(path);
50+
return stripLeadingSlashes(stripped.substring(_basePath.length));
51+
}
52+
53+
String _addBasePath(String serverPath) => _basePath.isEmpty
54+
? stripLeadingSlashes(serverPath)
55+
: '$_basePath/${stripLeadingSlashes(serverPath)}';
56+
57+
Future<Map<String, String>> _moduleProvider(
58+
MetadataProvider metadataProvider,
59+
) async =>
60+
(await metadataProvider.moduleToModulePath).map(
61+
(key, value) =>
62+
MapEntry(key, stripLeadingSlashes(removeJsExtension(value))),
63+
);
64+
65+
Future<String?> _moduleForServerPath(
66+
MetadataProvider metadataProvider,
67+
String serverPath,
68+
) async {
69+
final modulePathToModule = await metadataProvider.modulePathToModule;
70+
final relativeServerPath = _removeBasePath(serverPath);
71+
return modulePathToModule[relativeServerPath];
72+
}
73+
74+
Future<String> _serverPathForModule(
75+
MetadataProvider metadataProvider,
76+
String module,
77+
) async =>
78+
_addBasePath((await metadataProvider.moduleToModulePath)[module] ?? '');
79+
80+
Future<String> _sourceMapPathForModule(
81+
MetadataProvider metadataProvider,
82+
String module,
83+
) async =>
84+
_addBasePath((await metadataProvider.moduleToSourceMap)[module] ?? '');
85+
86+
String? _serverPathForAppUri(String appUrl) {
87+
final appUri = Uri.parse(appUrl);
88+
if (appUri.isScheme('org-dartlang-app')) {
89+
return _addBasePath(appUri.path);
90+
}
91+
if (appUri.isScheme('package')) {
92+
final resolved = _packageUriMapper.packageUriToServerPath(appUri);
93+
if (resolved != null) {
94+
return resolved;
95+
}
96+
}
97+
return null;
98+
}
99+
100+
Future<Map<String, ModuleInfo>> _moduleInfoForProvider(
101+
MetadataProvider metadataProvider,
102+
) async {
103+
final modules = await metadataProvider.moduleToModulePath;
104+
final result = <String, ModuleInfo>{};
105+
for (var module in modules.keys) {
106+
final modulePath = modules[module]!;
107+
result[module] = ModuleInfo(
108+
// TODO: Save locations of full kernel files in ddc metadata.
109+
// Issue: https://github.com/dart-lang/sdk/issues/43684
110+
p.setExtension(modulePath, '.full.dill'),
111+
p.setExtension(modulePath, '.dill'),
112+
);
113+
}
114+
return result;
115+
}
116+
}

dwds/lib/src/loaders/legacy.dart

+73-1
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,72 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5+
import 'dart:convert';
6+
57
import 'package:dwds/src/debugging/metadata/provider.dart';
68
import 'package:dwds/src/loaders/strategy.dart';
79
import 'package:dwds/src/readers/asset_reader.dart';
810
import 'package:dwds/src/services/expression_compiler.dart';
11+
import 'package:path/path.dart' as p;
912
import 'package:shelf/shelf.dart';
1013

14+
String removeJsExtension(String path) =>
15+
path.endsWith('.js') ? p.withoutExtension(path) : path;
16+
17+
String addJsExtension(String path) => '$path.js';
18+
19+
/// JavaScript snippet to determine the base URL of the current path.
20+
const _baseUrlScript = '''
21+
var baseUrl = (function () {
22+
// Attempt to detect --precompiled mode for tests, and set the base url
23+
// appropriately, otherwise set it to '/'.
24+
var pathParts = location.pathname.split("/");
25+
if (pathParts[0] == "") {
26+
pathParts.shift();
27+
}
28+
if (pathParts.length > 1 && pathParts[1] == "test") {
29+
return "/" + pathParts.slice(0, 2).join("/") + "/";
30+
}
31+
// Attempt to detect base url using <base href> html tag
32+
// base href should start and end with "/"
33+
if (typeof document !== 'undefined') {
34+
var el = document.getElementsByTagName('base');
35+
if (el && el[0] && el[0].getAttribute("href") && el[0].getAttribute
36+
("href").startsWith("/") && el[0].getAttribute("href").endsWith("/")){
37+
return el[0].getAttribute("href");
38+
}
39+
}
40+
// return default value
41+
return "/";
42+
}());
43+
''';
44+
1145
/// A load strategy for the legacy module system.
1246
class LegacyStrategy extends LoadStrategy {
1347
@override
1448
final ReloadConfiguration reloadConfiguration;
1549

50+
/// Returns a map of module name to corresponding server path (excluding .js)
51+
/// for the provided Dart application entrypoint.
52+
///
53+
/// For example:
54+
///
55+
/// web/main -> main.ddc
56+
/// packages/path/path -> packages/path/path.ddc
57+
///
58+
final Future<Map<String, String>> Function(MetadataProvider metadataProvider)
59+
_moduleProvider;
60+
61+
/// Returns a map of module name to corresponding digest value.
62+
///
63+
/// For example:
64+
///
65+
/// web/main -> 8363b363f74b41cac955024ab8b94a3f
66+
/// packages/path/path -> d348c2a4647e998011fe305f74f22961
67+
///
68+
final Future<Map<String, String>> Function(MetadataProvider metadataProvider)
69+
_digestsProvider;
70+
1671
/// Returns the module for the corresponding server path.
1772
///
1873
/// For example:
@@ -75,6 +130,8 @@ class LegacyStrategy extends LoadStrategy {
75130

76131
LegacyStrategy(
77132
this.reloadConfiguration,
133+
this._moduleProvider,
134+
this._digestsProvider,
78135
this._moduleForServerPath,
79136
this._serverPathForModule,
80137
this._sourceMapPathForModule,
@@ -102,12 +159,27 @@ class LegacyStrategy extends LoadStrategy {
102159
String get loadModuleSnippet => 'dart_library.import';
103160

104161
@override
105-
Future<String> bootstrapFor(String entrypoint) async => '';
162+
Future<String> bootstrapFor(String entrypoint) async =>
163+
await _legacyLoaderSetup(entrypoint);
106164

107165
@override
108166
String loadClientSnippet(String clientScript) =>
109167
'window.\$dartLoader.forceLoadModule("$clientScript");\n';
110168

169+
Future<String> _legacyLoaderSetup(String entrypoint) async {
170+
final metadataProvider = metadataProviderFor(entrypoint);
171+
final modulePaths = await _moduleProvider(metadataProvider);
172+
final scripts = <Map<String, String?>>[];
173+
modulePaths.forEach((name, path) {
174+
scripts.add(<String, String>{'src': '$path.js', 'id': name});
175+
});
176+
return '''
177+
$_baseUrlScript
178+
var scripts = ${const JsonEncoder.withIndent(" ").convert(scripts)};
179+
window.\$dartLoader.loadScripts(scripts);
180+
''';
181+
}
182+
111183
@override
112184
Future<String?> moduleForServerPath(String entrypoint, String serverPath) =>
113185
_moduleForServerPath(metadataProviderFor(entrypoint), serverPath);

0 commit comments

Comments
 (0)