Skip to content
7 changes: 3 additions & 4 deletions dwds/lib/src/debugging/metadata/function.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:async';

// @dart = 2.9

import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart';

import '../../loaders/strategy.dart';
Expand Down Expand Up @@ -43,8 +41,9 @@ class FunctionMetaData {
response,
evalContents: evalExpression,
);
var name = response.result['result']['value'] as String;
if (name.isEmpty) name = 'Closure';
final name = response.result?['result']?['value'] as String?;
if (name == null) return FunctionMetaData('<unknown>');
if (name.isEmpty) return FunctionMetaData('Closure');
return FunctionMetaData(name);
}
}
49 changes: 33 additions & 16 deletions dwds/lib/src/debugging/metadata/module_metadata.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.

// @dart = 2.9

/// Module metadata format version
///
/// Module reader always creates the current version but is able to read
Expand Down Expand Up @@ -77,10 +75,9 @@ class LibraryMetadata {
LibraryMetadata(this.name, this.importUri, this.partUris);

LibraryMetadata.fromJson(Map<String, dynamic> json)
: name = json['name'] as String,
importUri = json['importUri'] as String,
partUris =
List.castFrom<dynamic, String>(json['partUris'] as List<dynamic>);
: name = _readRequiredField(json, 'name'),
importUri = _readRequiredField(json, 'importUri'),
partUris = _readOptionalList(json, 'partUris') ?? [];

Map<String, dynamic> toJson() {
return {
Expand All @@ -98,7 +95,7 @@ class LibraryMetadata {
/// See: https://goto.google.com/dart-web-debugger-metadata
class ModuleMetadata {
/// Metadata format version
String version;
late final String version;

/// Module name
///
Expand All @@ -125,8 +122,8 @@ class ModuleMetadata {

ModuleMetadata(this.name, this.closureName, this.sourceMapUri, this.moduleUri,
this.soundNullSafety,
{this.version}) {
version ??= ModuleMetadataVersion.current.version;
{String? ver}) {
version = ver ?? ModuleMetadataVersion.current.version;
}

/// Add [library] to metadata
Expand All @@ -145,12 +142,12 @@ class ModuleMetadata {
}

ModuleMetadata.fromJson(Map<String, dynamic> json)
: version = json['version'] as String,
name = json['name'] as String,
closureName = json['closureName'] as String,
sourceMapUri = json['sourceMapUri'] as String,
moduleUri = json['moduleUri'] as String,
soundNullSafety = (json['soundNullSafety'] as bool) ?? false {
: version = _readRequiredField(json, 'version'),
name = _readRequiredField(json, 'name'),
closureName = _readRequiredField(json, 'closureName'),
sourceMapUri = _readRequiredField(json, 'sourceMapUri'),
moduleUri = _readRequiredField(json, 'moduleUri'),
soundNullSafety = _readOptionalField(json, 'soundNullSafety') ?? false {
if (!ModuleMetadataVersion.current.isCompatibleWith(version) &&
!ModuleMetadataVersion.previous.isCompatibleWith(version)) {
throw Exception('Unsupported metadata version $version. '
Expand All @@ -159,7 +156,7 @@ class ModuleMetadata {
'\n ${ModuleMetadataVersion.previous.version}');
}

for (var l in json['libraries'] as List<dynamic>) {
for (var l in _readRequiredList(json, 'libraries')) {
addLibrary(LibraryMetadata.fromJson(l as Map<String, dynamic>));
}
}
Expand All @@ -176,3 +173,23 @@ class ModuleMetadata {
};
}
}

T _readRequiredField<T>(Map<String, dynamic> json, String field) {
if (!json.containsKey(field)) {
throw FormatException('Required field $field is not set in $json');
}
return json[field]! as T;
}

T? _readOptionalField<T>(Map<String, dynamic> json, String field) =>
json[field] as T?;

List<T> _readRequiredList<T>(Map<String, dynamic> json, String field) {
final list = _readRequiredField<List<dynamic>>(json, field);
return List.castFrom<dynamic, T>(list);
}

List<T>? _readOptionalList<T>(Map<String, dynamic> json, String field) {
final list = _readOptionalField<List<dynamic>>(json, field);
return list == null ? null : List.castFrom<dynamic, T>(list);
}
7 changes: 2 additions & 5 deletions dwds/lib/src/debugging/metadata/provider.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:async';

// @dart = 2.9

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

Expand Down Expand Up @@ -194,8 +192,7 @@ class MetadataProvider {
_addSdkMetadata();
for (var contents in merged.split('\n')) {
try {
if (contents == null ||
contents.isEmpty ||
if (contents.isEmpty ||
contents.startsWith('// intentionally empty:')) continue;
final moduleJson = json.decode(contents);
final metadata =
Expand Down Expand Up @@ -237,7 +234,7 @@ class MetadataProvider {
for (var path in library.partUris) {
// Parts in metadata are relative to the library Uri directory.
final partPath = p.url.join(p.dirname(library.importUri), path);
_scripts[library.importUri].add(partPath);
_scripts[library.importUri]!.add(partPath);
_scriptToModule[partPath] = metadata.name;
}
}
Expand Down
5 changes: 4 additions & 1 deletion dwds/lib/src/handlers/injector.dart
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,10 @@ class DwdsInjector {
return response.change(body: body, headers: newHeaders);
} else {
final loadResponse = await _loadStrategy.handler(request);
if (loadResponse != null) return loadResponse;
if (loadResponse != null &&
loadResponse.statusCode != HttpStatus.notFound) {
return loadResponse;
}
return innerHandler(request);
}
};
Expand Down
59 changes: 38 additions & 21 deletions dwds/lib/src/loaders/build_runner_require.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@
// 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.

// @dart = 2.9

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

import 'package:logging/logging.dart';
import 'package:path/path.dart' as p;
import 'package:shelf/shelf.dart';

Expand All @@ -18,26 +17,28 @@ import 'require.dart';

/// Provides a [RequireStrategy] suitable for use with `package:build_runner`.
class BuildRunnerRequireStrategyProvider {
final _logger = Logger('BuildRunnerRequireStrategyProvider');

final Handler _assetHandler;
final ReloadConfiguration _configuration;
final AssetReader _assetReader;

RequireStrategy _requireStrategy;
late final RequireStrategy _requireStrategy = RequireStrategy(
_configuration,
_moduleProvider,
_digestsProvider,
_moduleForServerPath,
_serverPathForModule,
_sourceMapPathForModule,
_serverPathForAppUri,
_moduleInfoForProvider,
_assetReader,
);

BuildRunnerRequireStrategyProvider(
this._assetHandler, this._configuration, this._assetReader);

RequireStrategy get strategy => _requireStrategy ??= RequireStrategy(
_configuration,
_moduleProvider,
_digestsProvider,
_moduleForServerPath,
_serverPathForModule,
_sourceMapPathForModule,
_serverPathForAppUri,
_moduleInfoForProvider,
_assetReader,
);
RequireStrategy get strategy => _requireStrategy;

Future<Map<String, String>> _digestsProvider(
MetadataProvider metadataProvider) async {
Expand All @@ -51,9 +52,18 @@ class BuildRunnerRequireStrategyProvider {
throw StateError('Could not read digests at path: $digestsPath');
}
final body = await response.readAsString();
final digests = json.decode(body) as Map<String, dynamic>;

for (final key in digests.keys) {
if (!modules.containsKey(key)) {
_logger.warning('Digest key $key is not a module name.');
}
}

return {
for (var entry in (json.decode(body) as Map<String, dynamic>).entries)
modules[entry.key]: entry.value as String,
for (var entry in digests.entries)
if (modules.containsKey(entry.key))
modules[entry.key]!: entry.value as String,
};
}

Expand All @@ -62,10 +72,17 @@ class BuildRunnerRequireStrategyProvider {
(await metadataProvider.moduleToModulePath).map((key, value) =>
MapEntry(key, stripTopLevelDirectory(removeJsExtension(value))));

Future<String> _moduleForServerPath(
MetadataProvider metadataProvider, String serverPath) async =>
(await metadataProvider.modulePathToModule).map((key, value) => MapEntry(
stripTopLevelDirectory(key), value))[relativizePath(serverPath)];
Future<String?> _moduleForServerPath(
MetadataProvider metadataProvider, String serverPath) async {
final modulePathToModule = await metadataProvider.modulePathToModule;
final relativePath = relativizePath(serverPath);
for (var e in modulePathToModule.entries) {
if (stripTopLevelDirectory(e.key) == relativePath) {
return e.value;
}
}
return null;
}

Future<String> _serverPathForModule(
MetadataProvider metadataProvider, String module) async {
Expand All @@ -80,7 +97,7 @@ class BuildRunnerRequireStrategyProvider {
return stripTopLevelDirectory(path);
}

String _serverPathForAppUri(String appUri) {
String? _serverPathForAppUri(String appUri) {
if (appUri.startsWith('org-dartlang-app:')) {
// We skip the root from which we are serving.
return Uri.parse(appUri).pathSegments.skip(1).join('/');
Expand Down
42 changes: 20 additions & 22 deletions dwds/lib/src/loaders/frontend_server_require.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// @dart = 2.9

import 'package:path/path.dart' as p;

import '../debugging/metadata/provider.dart';
Expand All @@ -19,22 +17,22 @@ class FrontendServerRequireStrategyProvider {
final Future<Map<String, String>> Function() _digestsProvider;
final String _basePath;

RequireStrategy _requireStrategy;
late final RequireStrategy _requireStrategy = RequireStrategy(
_configuration,
_moduleProvider,
(_) => _digestsProvider(),
_moduleForServerPath,
_serverPathForModule,
_sourceMapPathForModule,
_serverPathForAppUri,
_moduleInfoForProvider,
_assetReader,
);

FrontendServerRequireStrategyProvider(this._configuration, this._assetReader,
this._digestsProvider, this._basePath);

RequireStrategy get strategy => _requireStrategy ??= RequireStrategy(
_configuration,
_moduleProvider,
(_) => _digestsProvider(),
_moduleForServerPath,
_serverPathForModule,
_sourceMapPathForModule,
_serverPathForAppUri,
_moduleInfoForProvider,
_assetReader,
);
RequireStrategy get strategy => _requireStrategy;

String _removeBasePath(String path) {
if (_basePath.isEmpty) return path;
Expand All @@ -43,20 +41,20 @@ class FrontendServerRequireStrategyProvider {
return path.startsWith(base) ? path.substring(base.length) : path;
}

String _addBasePath(String serverPath) =>
_basePath == null || _basePath.isEmpty
? relativizePath(serverPath)
: '$_basePath/${relativizePath(serverPath)}';
String _addBasePath(String serverPath) => _basePath.isEmpty
? relativizePath(serverPath)
: '$_basePath/${relativizePath(serverPath)}';

Future<Map<String, String>> _moduleProvider(
MetadataProvider metadataProvider) async =>
(await metadataProvider.moduleToModulePath).map((key, value) =>
MapEntry(key, relativizePath(removeJsExtension(value))));

Future<String> _moduleForServerPath(
Future<String?> _moduleForServerPath(
MetadataProvider metadataProvider, String serverPath) async {
final modulePathToModule = await metadataProvider.modulePathToModule;
return modulePathToModule[_removeBasePath(serverPath)];
final relativeServerPath = _removeBasePath(serverPath);
return modulePathToModule[relativeServerPath];
}

Future<String> _serverPathForModule(
Expand All @@ -67,7 +65,7 @@ class FrontendServerRequireStrategyProvider {
MetadataProvider metadataProvider, String module) async =>
_addBasePath((await metadataProvider.moduleToSourceMap)[module] ?? '');

String _serverPathForAppUri(String appUri) {
String? _serverPathForAppUri(String appUri) {
if (appUri.startsWith('org-dartlang-app:')) {
return _addBasePath(Uri.parse(appUri).path);
}
Expand All @@ -79,7 +77,7 @@ class FrontendServerRequireStrategyProvider {
final modules = await metadataProvider.moduleToModulePath;
final result = <String, ModuleInfo>{};
for (var module in modules.keys) {
final modulePath = modules[module];
final modulePath = modules[module]!;
result[module] = ModuleInfo(
// TODO: Save locations of full kernel files in ddc metadata.
// Issue: https://github.com/dart-lang/sdk/issues/43684
Expand Down
8 changes: 3 additions & 5 deletions dwds/lib/src/loaders/legacy.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.

// @dart = 2.9

import 'package:shelf/shelf.dart';

import '../debugging/metadata/provider.dart';
Expand Down Expand Up @@ -61,7 +59,7 @@ class LegacyStrategy extends LoadStrategy {
///
/// Will return `null` if the provided uri is not
/// an app URI.
final String Function(String appUri) _serverPathForAppUri;
final String? Function(String appUri) _serverPathForAppUri;

LegacyStrategy(
this.reloadConfiguration,
Expand All @@ -74,7 +72,7 @@ class LegacyStrategy extends LoadStrategy {
) : super(assetReader);

@override
Handler get handler => (request) => null;
Handler get handler => (request) => Response.notFound(request.url);

@override
String get id => 'legacy';
Expand Down Expand Up @@ -121,5 +119,5 @@ class LegacyStrategy extends LoadStrategy {
_sourceMapPathForModule(metadataProviderFor(entrypoint), module);

@override
String serverPathForAppUri(String appUri) => _serverPathForAppUri(appUri);
String? serverPathForAppUri(String appUri) => _serverPathForAppUri(appUri);
}
Loading