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