Files
sdk/pkg/dev_compiler/test/memory_compiler.dart
T
Nicholas Shahan f91050ca91 [ddc] Add visitor for hot reload deltas
Initially this visitor will reject reloads (by throwing an Exception).
Future changes will add the ability to record data about the delta to
guide the JavaScript compilation decisions.

- Rejects deltas that delete all const constructors from a class
  (making it non-const).
- Adds ability to test the visitor directly by compiling components
  from source via an in-memory compiler.
- Updates DDC frontend_server compiles to write errors to the output
  stream.

Change-Id: Ib318f42d28367416983266a214f97821a38a2913
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/401600
Reviewed-by: Jens Johansen <jensj@google.com>
Reviewed-by: Srujan Gaddam <srujzs@google.com>
Reviewed-by: Mark Zhou <markzipan@google.com>
Reviewed-by: Nate Biggs <natebiggs@google.com>
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Commit-Queue: Nicholas Shahan <nshahan@google.com>
2025-01-10 10:20:42 -08:00

105 lines
3.9 KiB
Dart

// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
// 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 'package:dev_compiler/dev_compiler.dart';
import 'package:dev_compiler/src/command/command.dart';
import 'package:dev_compiler/src/js_ast/js_ast.dart';
import 'package:front_end/src/api_unstable/ddc.dart' as fe;
import 'package:kernel/target/targets.dart';
/// Result compiling using [compileFromMemory].
///
/// This is meant for testing and therefore include not only the resulting
/// [Program] various artifacts of the compilation.
class MemoryCompilerResult {
final fe.DdcResult ddcResult;
final ProgramCompiler compiler;
final Program program;
final List<fe.DiagnosticMessage> errors;
MemoryCompilerResult(
this.ddcResult, this.compiler, this.program, this.errors);
}
/// Result of compiling using [componentFromMemory].
///
/// This is meant for use in tests and performs the front end compilation to
/// components without calling DDC.
class MemoryComponentResult {
final fe.DdcResult ddcResult;
final List<fe.DiagnosticMessage> errors;
MemoryComponentResult(this.ddcResult, this.errors);
}
/// Uri used as the base uri for files provided in memory through the
/// [MemoryFileSystem].
Uri memoryDirectory = Uri.parse('memory://');
/// Compiles [entryPoint] to a kernel `Component` using the [memoryFiles] as
/// sources.
///
/// [memoryFiles] maps relative paths to their source text. [entryPoint] must
/// be absolute, using [memoryDirectory] as a base uri to refer to a file from
/// [memoryFiles].
Future<MemoryComponentResult> componentFromMemory(
Map<String, String> memoryFiles, Uri entryPoint,
{Map<fe.ExperimentalFlag, bool>? explicitExperimentalFlags}) async {
var errors = <fe.DiagnosticMessage>[];
void diagnosticMessageHandler(fe.DiagnosticMessage message) {
if (message.severity == fe.Severity.error) {
errors.add(message);
}
fe.printDiagnosticMessage(message, print);
}
var memoryFileSystem = fe.MemoryFileSystem(memoryDirectory);
for (var entry in memoryFiles.entries) {
memoryFileSystem
.entityForUri(memoryDirectory.resolve(entry.key))
.writeAsStringSync(entry.value);
}
var compilerState = fe.initializeCompiler(
null,
false,
sourcePathToUri(getSdkPath()),
sourcePathToUri(defaultSdkSummaryPath),
null,
sourcePathToUri(defaultLibrarySpecPath),
[],
DevCompilerTarget(
TargetFlags(trackWidgetCreation: false, soundNullSafety: true)),
fileSystem: fe.HybridFileSystem(memoryFileSystem),
environmentDefines: {},
explicitExperimentalFlags: explicitExperimentalFlags,
nnbdMode: fe.NnbdMode.Strong);
var result =
await fe.compile(compilerState, [entryPoint], diagnosticMessageHandler);
if (result == null) {
throw 'Memory compilation failed';
}
return MemoryComponentResult(result, errors);
}
/// Compiles [entryPoint] to JavaScript using the [memoryFiles] as sources.
///
/// [memoryFiles] maps relative paths to their source text. [entryPoint] must
/// be absolute, using [memoryDirectory] as a base uri to refer to a file from
/// [memoryFiles].
Future<MemoryCompilerResult> compileFromMemory(
Map<String, String> memoryFiles, Uri entryPoint,
{Map<fe.ExperimentalFlag, bool>? explicitExperimentalFlags}) async {
var MemoryComponentResult(ddcResult: result, :errors) =
await componentFromMemory(memoryFiles, entryPoint);
var options = Options(moduleName: 'test');
var compiler =
// TODO(nshahan): Do we need to support [importToSummary] and
// [summaryToModule].
ProgramCompiler(result.component, result.classHierarchy, options, {}, {});
var jsModule = compiler.emitModule(result.compiledLibraries);
return MemoryCompilerResult(result, compiler, jsModule, errors);
}