blob: b044cf4afbc5360bdf46b4ab5c8ce2fba3d5fc4d [file] [log] [blame]
// Copyright (c) 2019, 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 'dart:convert';
import 'dart:js_interop';
import 'package:dwds/data/isolate_events.dart';
import 'package:dwds/data/serializers.dart';
import 'package:dwds/src/sockets.dart';
import 'package:web/web.dart';
import 'ddc_library_bundle_restarter.dart';
import 'restarter.dart';
class ReloadingManager {
final SocketClient _client;
final Restarter _restarter;
ReloadingManager(this._client, this._restarter);
/// Attempts to perform a hot restart.
///
/// [runId] is used to hot restart code in the browser for all apps that
/// - are loaded on the same page
/// - called hotRestart with the same runId
///
/// The apps are restarted at the same time on the first call.
///
/// [reloadedSourcesPath] is the path to a JSONified list of maps that
/// represents the sources that were reloaded in this restart and follows the
/// following format:
///
/// ```json
/// [
/// {
/// "src": "<base_uri>/<file_name>",
/// "module": "<module_name>",
/// "libraries": ["<lib1>", "<lib2>"],
/// },
/// ]
/// ```
///
/// `src`: A string that corresponds to the file path containing a DDC library
/// bundle.
/// `module`: The name of the library bundle in `src`.
/// `libraries`: An array of strings containing the libraries that were
/// compiled in `src`.
///
/// Returns either the JS version of the list of maps from
/// [reloadedSourcesPath] if [reloadedSourcesPath] is non-null and null
/// otherwise.
Future<JSArray<JSObject>?> hotRestart({
String? runId,
Future? readyToRunMain,
String? reloadedSourcesPath,
}) async {
_beforeRestart();
final result = await _restarter.restart(
runId: runId,
readyToRunMain: readyToRunMain,
reloadedSourcesPath: reloadedSourcesPath,
);
_afterRestart(result.$1);
return result.$2;
}
/// After a previous call to [hotReloadStart], completes the hot
/// reload by pushing the libraries into the Dart runtime.
Future<void> hotReloadEnd() async {
await _restarter.hotReloadEnd();
}
/// Using [reloadedSourcesPath] as the path to a JSONified list of maps which
/// follows the following format:
///
/// ```json
/// [
/// {
/// "src": "<base_uri>/<file_name>",
/// "module": "<module_name>",
/// "libraries": ["<lib1>", "<lib2>"],
/// },
/// ]
/// ```
///
/// computes the sources and libraries to reload, loads them into the page,
/// and returns a JS version of the list of maps.
///
/// `src`: A string that corresponds to the file path containing a DDC library
/// bundle.
/// `module`: The name of the library bundle in `src`.
/// `libraries`: An array of strings containing the libraries that were
/// compiled in `src`.
Future<JSArray<JSObject>> hotReloadStart(String reloadedSourcesPath) =>
_restarter.hotReloadStart(reloadedSourcesPath);
/// Does a hard reload of the application.
void reloadPage() {
window.location.reload();
}
/// Handles service extension requests by delegating to the appropriate restarter
Future<Map<String, dynamic>?> handleServiceExtension(
String method,
Map<String, dynamic> args,
) async {
final restarter = _restarter;
if (restarter is DdcLibraryBundleRestarter) {
return await restarter.handleServiceExtension(method, args);
}
// For other restarter types, return null to indicate not supported
return null;
}
void _afterRestart(bool succeeded) {
if (!succeeded) return;
// Notify package:dwds that the isolate has been created.
// package:dwds will respond with a [RunRequest].
_client.sink.add(jsonEncode(serializers.serialize(IsolateStart())));
}
void _beforeRestart() {
// Notify package:dwds that the isolate is about to exit.
_client.sink.add(jsonEncode(serializers.serialize(IsolateExit())));
}
}