David Iglesias b6a14724a8 [web] Add add/removeView JS methods. (flutter/engine#48106)
This PR adds:

* JS-interop types to expose addView/removeView from the running FlutterApp object on JavaScript.
  * Also, the options object that can be passed to `addView`.

### Issues:

* Fixes: https://github.com/flutter/flutter/issues/137377

### Info

Most interesting files:

* `app_bootstrap.dart` -> Adds the implementation for JS add/remove view.
* `js_app.dart` -> Adds the js-interop layer for the FlutterApp object, and the configuration type. (Two options: `hostElement` and `initialData`).
* `flutter_view_manager.dart` -> An abstraction over the `viewData` map that keeps related things together: viewData, js configuration options, register/unregister methods and a Stream<void> of modification events.

The rest of the changes were ""required"" to have a small demo that does anything (currently it lets me "register" views from javascript). I didn't add much in there, because probably it's already being worked on by @mdebbar; just fiddled with the constructor of the EngineFlutterView to create views from JS Config, and added a wrapper around the `viewData` map (`FlutterViewManager`) to prevent direct access to the Map.

## Usage

This is how I'm currently initializing my Flutter App, so I can "leak" the `flutterApp` to window and do things asynchronously after flutter loads:

```html
<script>
  window.addEventListener('load', async function(ev) {
    _flutter.loader.loadEntrypoint({
      onEntrypointLoaded: function(engineInitializer) {
        engineInitializer.initializeEngine({
          multiViewEnabled: true,
        }).then(function(appRunner) {
          return appRunner.runApp();
        }).then(onAppRunning);
      }
    });
    // Leak flutterApp to window so we can do async things...
    function onAppRunning(flutterApp) {
      console.log('Running app', flutterApp);
      window.flutterApp = flutterApp;
    }
  });
</script>
```

This to test:

 * Go on your JS console and use `flutterApp.addView({})` and see how that returns a Promise for the viewId it just added,
 * Now do `flutterApp.removeView(0)` (removes the implicitView), and see how everything starts crashing! (as expected) 
   * Get out of this weird state with a hot reload 🥳

[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
2023-11-21 15:30:07 +00:00
Languages
Dart 75%
C++ 16.5%
Objective-C++ 2.9%
Java 2.8%
Objective-C 0.7%
Other 1.9%