Skip to content

Commit

Permalink
Support wasm source maps (#3759)
Browse files Browse the repository at this point in the history
Fixes #3757
  • Loading branch information
jakemac53 authored Oct 7, 2024
1 parent 144c598 commit 387401f
Show file tree
Hide file tree
Showing 11 changed files with 54 additions and 50 deletions.
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ pubspec.lock
# Common build output
/*/build/

# Include .packages files from tests which are hand coded
!build_runner_core/test/fixtures/**/.dart_tool/
# Include package config files from tests which are hand coded
!build_runner_core/test/fixtures/**/.dart_tool/package_config.json
!build_runner_core/test/fixtures/**/pubspec.lock

# Extra files from dart2js that we don't want
Expand Down
4 changes: 4 additions & 0 deletions build_web_compilers/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 4.1.0-beta.2

- Add source maps for dart2wasm builds.

## 4.1.0-beta.1

- Fix loading compiled modules from subdirectories.
Expand Down
1 change: 1 addition & 0 deletions build_web_compilers/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ builders:
- .digests
- .dart.ddc_merged_metadata
- .wasm
- .wasm.map
- .mjs
required_inputs:
- .dart
Expand Down
28 changes: 21 additions & 7 deletions build_web_compilers/lib/src/common.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// 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 'dart:io';

import 'package:build/build.dart';
Expand Down Expand Up @@ -38,21 +39,34 @@ void validateOptions(Map<String, dynamic> config, List<String> supportedOptions,
}
}

/// Fixes up the [uris] from a source map so they make sense in a browser
/// context.
/// If [id] exists, assume it is a source map and fix up the source uris from
/// it so they make sense in a browser context, then write the modified version
/// using [writer].
///
/// - Strips the scheme from the uri
/// - Strips the top level directory if its not `packages`
///
/// Copied to `web/stack_trace_mapper.dart`, these need to be kept in sync.
List<String> fixSourceMapSources(List<String> uris) {
return uris.map((source) {
Future<void> fixAndCopySourceMap(
AssetId id, ScratchSpace scratchSpace, AssetWriter writer) async {
// Copied to `web/stack_trace_mapper.dart`, these need to be kept in sync.
String fixMappedSource(String source) {
var uri = Uri.parse(source);
// We only want to rewrite multi-root scheme uris.
if (uri.scheme.isEmpty) return source;
var newSegments = uri.pathSegments.first == 'packages'
? uri.pathSegments
: uri.pathSegments.skip(1);
return Uri(path: p.url.joinAll(['/', ...newSegments])).toString();
}).toList();
}

var file = scratchSpace.fileFor(id);
if (await file.exists()) {
var content = await file.readAsString();
var json = jsonDecode(content) as Map<String, Object?>;
var sources = json['sources'] as List<Object?>;
// Modify `sources` in place for fewer allocations.
for (var i = 0; i < sources.length; i++) {
sources[i] = fixMappedSource(sources[i] as String);
}
await writer.writeAsString(id, jsonEncode(json));
}
}
21 changes: 4 additions & 17 deletions build_web_compilers/lib/src/dart2js_bootstrap.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import 'package:glob/glob.dart';
import 'package:glob/list_local_fs.dart';
import 'package:path/path.dart' as p;
import 'package:pool/pool.dart';
import 'package:scratch_space/scratch_space.dart';

import 'common.dart';
import 'platforms.dart';
Expand Down Expand Up @@ -140,28 +139,16 @@ https://github.com/dart-lang/build/blob/master/docs/faq.md#how-can-i-resolve-ski
// Explicitly write out the original js file and sourcemap - we can't output
// these as part of the archive because they already have asset nodes.
await scratchSpace.copyOutput(jsOutputId, buildStep);
var jsSourceMapId =
dartEntrypointId.changeExtension(jsEntrypointSourceMapExtension);
await _copyModifiedSourceMap(jsSourceMapId, scratchSpace, buildStep);
await fixAndCopySourceMap(
dartEntrypointId.changeExtension(jsEntrypointSourceMapExtension),
scratchSpace,
buildStep);
} else {
log.severe('ExitCode:${result.exitCode}\nStdOut:\n${result.stdout}\n'
'StdErr:\n${result.stderr}');
}
}

/// If [id] exists, modifies it to something the browser can understand and
/// writes it using [writer].
Future<void> _copyModifiedSourceMap(
AssetId id, ScratchSpace scratchSpace, AssetWriter writer) async {
var file = scratchSpace.fileFor(id);
if (await file.exists()) {
var content = await file.readAsString();
var json = jsonDecode(content) as Map<String, Object?>;
json['sources'] = fixSourceMapSources((json['sources'] as List).cast());
await writer.writeAsString(id, jsonEncode(json));
}
}

final _resourcePool = Pool(maxWorkersPerTask);

const _dart2jsVmArgsEnvVar = 'BUILD_DART2JS_VM_ARGS';
Expand Down
8 changes: 6 additions & 2 deletions build_web_compilers/lib/src/dart2wasm_bootstrap.dart
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,12 @@ https://github.com/dart-lang/build/blob/master/docs/faq.md#how-can-i-resolve-ski
if (result.exitCode == 0 && await wasmOutputFile.exists()) {
log.info('${result.stdout}\n${result.stderr}');

await scratchSpace.copyOutput(
dartEntrypointId.changeExtension(wasmExtension), buildStep);
await scratchSpace.copyOutput(wasmOutputId, buildStep);

await fixAndCopySourceMap(
dartEntrypointId.changeExtension(wasmSourceMapExtension),
scratchSpace,
buildStep);

final loaderContents = await scratchSpace
.fileFor(dartEntrypointId.changeExtension(moduleJsExtension))
Expand Down
19 changes: 7 additions & 12 deletions build_web_compilers/lib/src/dev_compiler_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -264,22 +264,17 @@ Future<void> _createDevCompilerModule(
}

if (debugMode) {
// We need to modify the sources in the sourcemap to remove the custom
// `multiRootScheme` that we use.
var sourceMapId =
module.primarySource.changeExtension(jsSourceMapExtension);
var file = scratchSpace.fileFor(sourceMapId);
var content = await file.readAsString();
var json = jsonDecode(content) as Map<String, Object?>;
json['sources'] = fixSourceMapSources((json['sources'] as List).cast());
await buildStep.writeAsString(sourceMapId, jsonEncode(json));
await fixAndCopySourceMap(
module.primarySource.changeExtension(jsSourceMapExtension),
scratchSpace,
buildStep);

// Copy the metadata output, modifying its contents to remove the temp
// directory from paths
var metadataId = module.primarySource.changeExtension(metadataExtension);
file = scratchSpace.fileFor(metadataId);
content = await file.readAsString();
json = jsonDecode(content) as Map<String, Object?>;
var file = scratchSpace.fileFor(metadataId);
var content = await file.readAsString();
var json = jsonDecode(content) as Map<String, Object?>;
_fixMetadataSources(json, scratchSpace.tempDir.uri);
await buildStep.writeAsString(metadataId, jsonEncode(json));

Expand Down
12 changes: 3 additions & 9 deletions build_web_compilers/lib/src/sdk_js_compile_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.

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

import 'package:bazel_worker/bazel_worker.dart';
Expand Down Expand Up @@ -124,12 +123,7 @@ Future<void> _createDevCompilerModule(

// Copy the output back using the buildStep.
await scratchSpace.copyOutput(jsOutputId, buildStep);
// We need to modify the sources in the sourcemap to remove the custom
// `multiRootScheme` that we use.
var sourceMapId = jsOutputId.changeExtension(_jsSourceMapExtension);
var file = scratchSpace.fileFor(sourceMapId);
var content = await file.readAsString();
var json = jsonDecode(content) as Map<String, Object?>;
json['sources'] = fixSourceMapSources((json['sources'] as List).cast());
await buildStep.writeAsString(sourceMapId, jsonEncode(json));

await fixAndCopySourceMap(jsOutputId.changeExtension(_jsSourceMapExtension),
scratchSpace, buildStep);
}
2 changes: 2 additions & 0 deletions build_web_compilers/lib/src/web_entrypoint_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import 'dev_compiler_bootstrap.dart';
const ddcBootstrapExtension = '.dart.bootstrap.js';
const jsEntrypointExtension = '.dart.js';
const wasmExtension = '.wasm';
const wasmSourceMapExtension = '.wasm.map';
const moduleJsExtension = '.mjs';
const jsEntrypointSourceMapExtension = '.dart.js.map';
const jsEntrypointArchiveExtension = '.dart.js.tar.gz';
Expand Down Expand Up @@ -244,6 +245,7 @@ final class EntrypointBuilderOptions {
if (optionsFor(WebCompiler.Dart2Wasm) case final dart2wasm?) ...[
dart2wasm.extension,
wasmExtension,
wasmSourceMapExtension,
],
if (loaderExtension case final loader?) loader,
]
Expand Down
2 changes: 1 addition & 1 deletion build_web_compilers/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: build_web_compilers
version: 4.1.0-beta.1
version: 4.1.0-beta.2
description: Builder implementations wrapping the dart2js and DDC compilers.
repository: https://github.com/dart-lang/build/tree/master/build_web_compilers
# This package can't be part of the workspace because it requires a very recent
Expand Down
3 changes: 3 additions & 0 deletions build_web_compilers/test/dart2wasm_bootstrap_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ void main() {
outputs: {
'a|web/index.mjs': anything,
'a|web/index.wasm': anything,
'a|web/index.wasm.map': anything,
'a|web/index.dart.js': decodedMatches(contains('compileStreaming')),
},
);
Expand All @@ -62,6 +63,7 @@ void main() {
outputs: {
'a|web/index.mjs': anything,
'a|web/index.wasm': anything,
'a|web/index.wasm.map': anything,
'a|web/index.dart.js.tar.gz': anything,
'a|web/index.dart2js.js': decodedMatches(contains('Hello world!')),
'a|web/index.dart.js': decodedMatches(
Expand Down Expand Up @@ -96,6 +98,7 @@ void main() {
outputs: {
'a|web/index.mjs': anything,
'a|web/index.wasm': anything,
'a|web/index.wasm.map': anything,
'a|web/index.dart.js.tar.gz': anything,
'a|web/index.dart2js.js': decodedMatches(contains('Hello world!')),
},
Expand Down

0 comments on commit 387401f

Please sign in to comment.