| // 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()))); |
| } |
| } |