String _decorateJavaScript()

in lib/services/execution_iframe.dart [97:210]


  String _decorateJavaScript(
    String javaScript, {
    required String? modulesBaseUrl,
    required bool requireFirebase,
  }) {
    final completeScript = StringBuffer();
    final usesRequireJs = modulesBaseUrl != null;
    // postMessagePrint:
    completeScript.writeln('''
var testKey = '$testKey';

function dartPrint(message) {
  if (message.startsWith(testKey)) {
    var resultMsg = JSON.parse(message.substring(testKey.length));
    resultMsg.sender = 'frame';
    resultMsg.type = 'testResult';
    parent.postMessage(resultMsg, '*');
  } else {
    parent.postMessage(
      {'sender': 'frame', 'type': 'stdout', 'message': message.toString()}, '*');
  }
}
''');
    if (usesRequireJs) {
      completeScript.writeln('''
// Unload previous version.
require.undef('dartpad_main');
''');
    }

    // The JavaScript exception handling for DartPad catches both errors
    // directly raised by `main()` (in which case we might have useful Dart
    // exception information we don't want to discard), as well as errors
    // generated by other means, like assertion errors when starting up
    // asynchronous functions.
    //
    // To avoid duplicating error messages on the DartPad console, we signal to
    // `window.onerror` that we've already sent a dartMainRunner message by
    // flipping _thrownDartMainRunner to true.  Some platforms don't populate
    // error so avoid using it if it is null.
    //
    // This seems to produce both the stack traces we expect in inspector and
    // the right error messages on the console.
    completeScript.writeln('''
var _thrownDartMainRunner = false;

window.onerror = function(message, url, lineNumber, colno, error) {
  if (!_thrownDartMainRunner) {
    var errorMessage = '';
    if (error != null) {
      errorMessage = 'Error: ' + error;
    } 
    parent.postMessage(
      {'sender': 'frame', 'type': 'stderr', 'message': message + errorMessage}, '*');
  }
  _thrownDartMainRunner = false;
};
''');

    if (usesRequireJs) {
      completeScript.writeln('''
require.config({
  "baseUrl": "$modulesBaseUrl",
  "waitSeconds": 60
});
''');
    }

    completeScript.writeln(javaScript);

    if (usesRequireJs) {
      completeScript.writeln('''
require(['dart_sdk'],
  function(sdk) {
    'use strict';
    sdk.developer._extensions.clear();
    sdk.dart.hotRestart();
});

require(["dartpad_main", "dart_sdk"], function(dartpad_main, dart_sdk) {
    // SDK initialization.
    dart_sdk.dart.setStartAsyncSynchronously(true);
    dart_sdk._isolate_helper.startRootIsolate(() => {}, []);

    // Loads the `dartpad_main` module and runs its bootstrapped main method.
    //
    // DDK provides the user's code in a RequireJS module, which exports an
    // object that looks something like this:
    //
    // {
    //       [random_tokens]__bootstrap: bootstrap,
    //       [random_tokens]__main: main
    // }
    //
    // The first of those properties holds the compiled code for the bootstrap
    // Dart file, which the server uses to wrap the user's code and wait on a
    // call to dart:ui's `webOnlyInitializePlatform` before executing any of it.
    //
    // The loop below iterates over the properties of the exported object,
    // looking for one that ends in "__bootstrap". Once found, it executes the
    // bootstrapped main method, which calls the user's main method, which
    // (presumably) calls runApp and starts Flutter's rendering.

    // TODO: simplify this once we are firmly in a post Flutter 1.24 world.
    for (var prop in dartpad_main) {
          if (prop.endsWith("bootstrap")) {
            dartpad_main[prop].main();
          }
    }});
''');
    }

    return completeScript.toString();
  }