mirror of
https://github.com/dart-lang/sdk
synced 2024-11-05 18:22:09 +00:00
Create an app snapshot of the Dart front end.
R=asiva@google.com, hausner@google.com, zra@google.com Review-Url: https://codereview.chromium.org/2655173002 .
This commit is contained in:
parent
1e0bf05aaf
commit
8c7111c967
6 changed files with 233 additions and 185 deletions
16
BUILD.gn
16
BUILD.gn
|
@ -42,6 +42,9 @@ group("runtime") {
|
|||
"runtime/bin:sample_extension",
|
||||
"runtime/bin:test_extension",
|
||||
"runtime/vm:patched_sdk",
|
||||
|
||||
# TODO(rmacnak): Link this into 'dart'
|
||||
"utils/kernel-service:kernel-service",
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -122,9 +125,7 @@ action("create_sdk") {
|
|||
rebase_path("$root_gen_dir"),
|
||||
]
|
||||
if (defined(is_fuchsia) && is_fuchsia_host) {
|
||||
args += [
|
||||
"--copy_libs"
|
||||
]
|
||||
args += [ "--copy_libs" ]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -173,11 +174,10 @@ group("samples") {
|
|||
]
|
||||
}
|
||||
|
||||
|
||||
# The rules below build a qemu Fuchsia OS image that includes the Dart tree
|
||||
# under /system/test/dart. Building this image is gated by the GN argument
|
||||
# 'dart_build_fuchsia_test_image' because building the image is slow.
|
||||
if (defined(is_fuchsia) && (is_fuchsia)) {
|
||||
if (defined(is_fuchsia) && is_fuchsia) {
|
||||
declare_args() {
|
||||
dart_build_fuchsia_test_image = false
|
||||
}
|
||||
|
@ -217,10 +217,10 @@ if (defined(is_fuchsia) && (is_fuchsia)) {
|
|||
action("generate_dart_test_image") {
|
||||
testonly = true
|
||||
deps = [
|
||||
"runtime/bin:dart",
|
||||
"runtime/bin:run_vm_tests",
|
||||
"runtime/bin:process_test",
|
||||
":generate_dart_test_manifest",
|
||||
"runtime/bin:dart",
|
||||
"runtime/bin:process_test",
|
||||
"runtime/bin:run_vm_tests",
|
||||
]
|
||||
|
||||
input = "$target_gen_dir/dart_test_tree.manifest"
|
||||
|
|
|
@ -809,6 +809,173 @@ static Dart_Handle EnvironmentCallback(Dart_Handle name) {
|
|||
static void SnapshotOnExitHook(int64_t exit_code);
|
||||
|
||||
|
||||
static const int64_t kAppSnapshotHeaderSize = 5 * kInt64Size;
|
||||
static const int64_t kAppSnapshotMagicNumber = 0xf6f6dcdc;
|
||||
static const int64_t kAppSnapshotPageSize = 4 * KB;
|
||||
|
||||
|
||||
static bool ReadAppSnapshotBlobs(const char* script_name,
|
||||
const uint8_t** vm_data_buffer,
|
||||
const uint8_t** vm_instructions_buffer,
|
||||
const uint8_t** isolate_data_buffer,
|
||||
const uint8_t** isolate_instructions_buffer) {
|
||||
File* file = File::Open(script_name, File::kRead);
|
||||
if (file == NULL) {
|
||||
return false;
|
||||
}
|
||||
if (file->Length() < kAppSnapshotHeaderSize) {
|
||||
file->Release();
|
||||
return false;
|
||||
}
|
||||
int64_t header[5];
|
||||
ASSERT(sizeof(header) == kAppSnapshotHeaderSize);
|
||||
if (!file->ReadFully(&header, kAppSnapshotHeaderSize)) {
|
||||
file->Release();
|
||||
return false;
|
||||
}
|
||||
if (header[0] != kAppSnapshotMagicNumber) {
|
||||
file->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
int64_t vm_data_size = header[1];
|
||||
int64_t vm_data_position =
|
||||
Utils::RoundUp(file->Position(), kAppSnapshotPageSize);
|
||||
int64_t vm_instructions_size = header[2];
|
||||
int64_t vm_instructions_position = vm_data_position + vm_data_size;
|
||||
if (vm_instructions_size != 0) {
|
||||
vm_instructions_position =
|
||||
Utils::RoundUp(vm_instructions_position, kAppSnapshotPageSize);
|
||||
}
|
||||
int64_t isolate_data_size = header[3];
|
||||
int64_t isolate_data_position = Utils::RoundUp(
|
||||
vm_instructions_position + vm_instructions_size, kAppSnapshotPageSize);
|
||||
int64_t isolate_instructions_size = header[4];
|
||||
int64_t isolate_instructions_position =
|
||||
isolate_data_position + isolate_data_size;
|
||||
if (isolate_instructions_size != 0) {
|
||||
isolate_instructions_position =
|
||||
Utils::RoundUp(isolate_instructions_position, kAppSnapshotPageSize);
|
||||
}
|
||||
|
||||
if (vm_data_size != 0) {
|
||||
*vm_data_buffer = reinterpret_cast<const uint8_t*>(
|
||||
file->Map(File::kReadOnly, vm_data_position, vm_data_size));
|
||||
if (vm_data_buffer == NULL) {
|
||||
Log::PrintErr("Failed to memory map snapshot\n");
|
||||
Platform::Exit(kErrorExitCode);
|
||||
}
|
||||
}
|
||||
|
||||
if (vm_instructions_size != 0) {
|
||||
*vm_instructions_buffer = reinterpret_cast<const uint8_t*>(file->Map(
|
||||
File::kReadExecute, vm_instructions_position, vm_instructions_size));
|
||||
if (*vm_instructions_buffer == NULL) {
|
||||
Log::PrintErr("Failed to memory map snapshot\n");
|
||||
Platform::Exit(kErrorExitCode);
|
||||
}
|
||||
}
|
||||
|
||||
*isolate_data_buffer = reinterpret_cast<const uint8_t*>(
|
||||
file->Map(File::kReadOnly, isolate_data_position, isolate_data_size));
|
||||
if (isolate_data_buffer == NULL) {
|
||||
Log::PrintErr("Failed to memory map snapshot\n");
|
||||
Platform::Exit(kErrorExitCode);
|
||||
}
|
||||
|
||||
if (isolate_instructions_size == 0) {
|
||||
*isolate_instructions_buffer = NULL;
|
||||
} else {
|
||||
*isolate_instructions_buffer = reinterpret_cast<const uint8_t*>(
|
||||
file->Map(File::kReadExecute, isolate_instructions_position,
|
||||
isolate_instructions_size));
|
||||
if (*isolate_instructions_buffer == NULL) {
|
||||
Log::PrintErr("Failed to memory map snapshot\n");
|
||||
Platform::Exit(kErrorExitCode);
|
||||
}
|
||||
}
|
||||
|
||||
file->Release();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#if defined(DART_PRECOMPILED_RUNTIME)
|
||||
static bool ReadAppSnapshotDynamicLibrary(
|
||||
const char* script_name,
|
||||
const uint8_t** vm_data_buffer,
|
||||
const uint8_t** vm_instructions_buffer,
|
||||
const uint8_t** isolate_data_buffer,
|
||||
const uint8_t** isolate_instructions_buffer) {
|
||||
void* library = Extensions::LoadExtensionLibrary(script_name);
|
||||
if (library == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*vm_data_buffer = reinterpret_cast<const uint8_t*>(
|
||||
Extensions::ResolveSymbol(library, kVmSnapshotDataSymbolName));
|
||||
if (*vm_data_buffer == NULL) {
|
||||
Log::PrintErr("Failed to resolve symbol '%s'\n", kVmSnapshotDataSymbolName);
|
||||
Platform::Exit(kErrorExitCode);
|
||||
}
|
||||
|
||||
*vm_instructions_buffer = reinterpret_cast<const uint8_t*>(
|
||||
Extensions::ResolveSymbol(library, kVmSnapshotInstructionsSymbolName));
|
||||
if (*vm_instructions_buffer == NULL) {
|
||||
Log::PrintErr("Failed to resolve symbol '%s'\n",
|
||||
kVmSnapshotInstructionsSymbolName);
|
||||
Platform::Exit(kErrorExitCode);
|
||||
}
|
||||
|
||||
*isolate_data_buffer = reinterpret_cast<const uint8_t*>(
|
||||
Extensions::ResolveSymbol(library, kIsolateSnapshotDataSymbolName));
|
||||
if (*isolate_data_buffer == NULL) {
|
||||
Log::PrintErr("Failed to resolve symbol '%s'\n",
|
||||
kIsolateSnapshotDataSymbolName);
|
||||
Platform::Exit(kErrorExitCode);
|
||||
}
|
||||
|
||||
*isolate_instructions_buffer =
|
||||
reinterpret_cast<const uint8_t*>(Extensions::ResolveSymbol(
|
||||
library, kIsolateSnapshotInstructionsSymbolName));
|
||||
if (*isolate_instructions_buffer == NULL) {
|
||||
Log::PrintErr("Failed to resolve symbol '%s'\n",
|
||||
kIsolateSnapshotInstructionsSymbolName);
|
||||
Platform::Exit(kErrorExitCode);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif // defined(DART_PRECOMPILED_RUNTIME)
|
||||
|
||||
|
||||
static bool ReadAppSnapshot(const char* script_name,
|
||||
const uint8_t** vm_data_buffer,
|
||||
const uint8_t** vm_instructions_buffer,
|
||||
const uint8_t** isolate_data_buffer,
|
||||
const uint8_t** isolate_instructions_buffer) {
|
||||
if (File::GetType(script_name, true) != File::kIsFile) {
|
||||
// If 'script_name' refers to a pipe, don't read to check for an app
|
||||
// snapshot since we cannot rewind if it isn't (and couldn't mmap it in
|
||||
// anyway if it was).
|
||||
return false;
|
||||
}
|
||||
if (ReadAppSnapshotBlobs(script_name, vm_data_buffer, vm_instructions_buffer,
|
||||
isolate_data_buffer, isolate_instructions_buffer)) {
|
||||
return true;
|
||||
}
|
||||
#if defined(DART_PRECOMPILED_RUNTIME)
|
||||
// For testing AOT with the standalone embedder, we also support loading
|
||||
// from a dynamic library to simulate what happens on iOS.
|
||||
return ReadAppSnapshotDynamicLibrary(
|
||||
script_name, vm_data_buffer, vm_instructions_buffer, isolate_data_buffer,
|
||||
isolate_instructions_buffer);
|
||||
#else
|
||||
return false;
|
||||
#endif // defined(DART_PRECOMPILED_RUNTIME)
|
||||
}
|
||||
|
||||
|
||||
// Returns true on success, false on failure.
|
||||
static Dart_Isolate CreateIsolateAndSetupHelper(bool is_main_isolate,
|
||||
const char* script_uri,
|
||||
|
@ -823,10 +990,10 @@ static Dart_Isolate CreateIsolateAndSetupHelper(bool is_main_isolate,
|
|||
if (!use_dart_frontend) {
|
||||
*error = strdup("Kernel isolate not supported.");
|
||||
return NULL;
|
||||
} else {
|
||||
if (packages_config == NULL) {
|
||||
packages_config = commandline_packages_file;
|
||||
}
|
||||
}
|
||||
script_uri = frontend_filename;
|
||||
if (packages_config == NULL) {
|
||||
packages_config = commandline_packages_file;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -849,6 +1016,19 @@ static Dart_Isolate CreateIsolateAndSetupHelper(bool is_main_isolate,
|
|||
isolate_run_app_snapshot = true;
|
||||
isolate_snapshot_data = app_isolate_snapshot_data;
|
||||
isolate_snapshot_instructions = app_isolate_snapshot_instructions;
|
||||
} else if (!is_main_isolate) {
|
||||
const uint8_t* file_vm_snapshot_data = NULL;
|
||||
const uint8_t* file_vm_snapshot_instructions = NULL;
|
||||
const uint8_t* file_isolate_snapshot_data = NULL;
|
||||
const uint8_t* file_isolate_snapshot_instructions = NULL;
|
||||
if (ReadAppSnapshot(
|
||||
script_uri, &file_vm_snapshot_data, &file_vm_snapshot_instructions,
|
||||
&file_isolate_snapshot_data, &file_isolate_snapshot_instructions)) {
|
||||
// TODO(rmacnak): We are leaking the snapshot when the isolate shuts down.
|
||||
isolate_run_app_snapshot = true;
|
||||
isolate_snapshot_data = file_isolate_snapshot_data;
|
||||
isolate_snapshot_instructions = file_isolate_snapshot_instructions;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -929,10 +1109,6 @@ static Dart_Isolate CreateIsolateAndSetupHelper(bool is_main_isolate,
|
|||
result = DartUtils::SetupServiceLoadPort();
|
||||
CHECK_RESULT(result);
|
||||
|
||||
if (Dart_IsKernelIsolate(isolate)) {
|
||||
script_uri = frontend_filename;
|
||||
}
|
||||
|
||||
// Setup package root if specified.
|
||||
result = DartUtils::SetupPackageRoot(package_root, packages_config);
|
||||
CHECK_RESULT(result);
|
||||
|
@ -1288,173 +1464,6 @@ static void WriteSnapshotFile(const char* filename,
|
|||
}
|
||||
|
||||
|
||||
static const int64_t kAppSnapshotHeaderSize = 5 * sizeof(int64_t); // NOLINT
|
||||
static const int64_t kAppSnapshotMagicNumber = 0xf6f6dcdc;
|
||||
static const int64_t kAppSnapshotPageSize = 4 * KB;
|
||||
|
||||
|
||||
static bool ReadAppSnapshotBlobs(const char* script_name,
|
||||
const uint8_t** vm_data_buffer,
|
||||
const uint8_t** vm_instructions_buffer,
|
||||
const uint8_t** isolate_data_buffer,
|
||||
const uint8_t** isolate_instructions_buffer) {
|
||||
File* file = File::Open(script_name, File::kRead);
|
||||
if (file == NULL) {
|
||||
return false;
|
||||
}
|
||||
if (file->Length() < kAppSnapshotHeaderSize) {
|
||||
file->Release();
|
||||
return false;
|
||||
}
|
||||
int64_t header[5];
|
||||
ASSERT(sizeof(header) == kAppSnapshotHeaderSize);
|
||||
if (!file->ReadFully(&header, kAppSnapshotHeaderSize)) {
|
||||
file->Release();
|
||||
return false;
|
||||
}
|
||||
if (header[0] != kAppSnapshotMagicNumber) {
|
||||
file->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
int64_t vm_data_size = header[1];
|
||||
int64_t vm_data_position =
|
||||
Utils::RoundUp(file->Position(), kAppSnapshotPageSize);
|
||||
int64_t vm_instructions_size = header[2];
|
||||
int64_t vm_instructions_position = vm_data_position + vm_data_size;
|
||||
if (vm_instructions_size != 0) {
|
||||
vm_instructions_position =
|
||||
Utils::RoundUp(vm_instructions_position, kAppSnapshotPageSize);
|
||||
}
|
||||
int64_t isolate_data_size = header[3];
|
||||
int64_t isolate_data_position = Utils::RoundUp(
|
||||
vm_instructions_position + vm_instructions_size, kAppSnapshotPageSize);
|
||||
int64_t isolate_instructions_size = header[4];
|
||||
int64_t isolate_instructions_position =
|
||||
isolate_data_position + isolate_data_size;
|
||||
if (isolate_instructions_size != 0) {
|
||||
isolate_instructions_position =
|
||||
Utils::RoundUp(isolate_instructions_position, kAppSnapshotPageSize);
|
||||
}
|
||||
|
||||
if (vm_data_size != 0) {
|
||||
*vm_data_buffer = reinterpret_cast<const uint8_t*>(
|
||||
file->Map(File::kReadOnly, vm_data_position, vm_data_size));
|
||||
if (vm_data_buffer == NULL) {
|
||||
Log::PrintErr("Failed to memory map snapshot\n");
|
||||
Platform::Exit(kErrorExitCode);
|
||||
}
|
||||
}
|
||||
|
||||
if (vm_instructions_size != 0) {
|
||||
*vm_instructions_buffer = reinterpret_cast<const uint8_t*>(file->Map(
|
||||
File::kReadExecute, vm_instructions_position, vm_instructions_size));
|
||||
if (*vm_instructions_buffer == NULL) {
|
||||
Log::PrintErr("Failed to memory map snapshot\n");
|
||||
Platform::Exit(kErrorExitCode);
|
||||
}
|
||||
}
|
||||
|
||||
*isolate_data_buffer = reinterpret_cast<const uint8_t*>(
|
||||
file->Map(File::kReadOnly, isolate_data_position, isolate_data_size));
|
||||
if (isolate_data_buffer == NULL) {
|
||||
Log::PrintErr("Failed to memory map snapshot\n");
|
||||
Platform::Exit(kErrorExitCode);
|
||||
}
|
||||
|
||||
if (isolate_instructions_size == 0) {
|
||||
*isolate_instructions_buffer = NULL;
|
||||
} else {
|
||||
*isolate_instructions_buffer = reinterpret_cast<const uint8_t*>(
|
||||
file->Map(File::kReadExecute, isolate_instructions_position,
|
||||
isolate_instructions_size));
|
||||
if (*isolate_instructions_buffer == NULL) {
|
||||
Log::PrintErr("Failed to memory map snapshot\n");
|
||||
Platform::Exit(kErrorExitCode);
|
||||
}
|
||||
}
|
||||
|
||||
file->Release();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#if defined(DART_PRECOMPILED_RUNTIME)
|
||||
static bool ReadAppSnapshotDynamicLibrary(
|
||||
const char* script_name,
|
||||
const uint8_t** vm_data_buffer,
|
||||
const uint8_t** vm_instructions_buffer,
|
||||
const uint8_t** isolate_data_buffer,
|
||||
const uint8_t** isolate_instructions_buffer) {
|
||||
void* library = Extensions::LoadExtensionLibrary(script_name);
|
||||
if (library == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*vm_data_buffer = reinterpret_cast<const uint8_t*>(
|
||||
Extensions::ResolveSymbol(library, kVmSnapshotDataSymbolName));
|
||||
if (*vm_data_buffer == NULL) {
|
||||
Log::PrintErr("Failed to resolve symbol '%s'\n", kVmSnapshotDataSymbolName);
|
||||
Platform::Exit(kErrorExitCode);
|
||||
}
|
||||
|
||||
*vm_instructions_buffer = reinterpret_cast<const uint8_t*>(
|
||||
Extensions::ResolveSymbol(library, kVmSnapshotInstructionsSymbolName));
|
||||
if (*vm_instructions_buffer == NULL) {
|
||||
Log::PrintErr("Failed to resolve symbol '%s'\n",
|
||||
kVmSnapshotInstructionsSymbolName);
|
||||
Platform::Exit(kErrorExitCode);
|
||||
}
|
||||
|
||||
*isolate_data_buffer = reinterpret_cast<const uint8_t*>(
|
||||
Extensions::ResolveSymbol(library, kIsolateSnapshotDataSymbolName));
|
||||
if (*isolate_data_buffer == NULL) {
|
||||
Log::PrintErr("Failed to resolve symbol '%s'\n",
|
||||
kIsolateSnapshotDataSymbolName);
|
||||
Platform::Exit(kErrorExitCode);
|
||||
}
|
||||
|
||||
*isolate_instructions_buffer =
|
||||
reinterpret_cast<const uint8_t*>(Extensions::ResolveSymbol(
|
||||
library, kIsolateSnapshotInstructionsSymbolName));
|
||||
if (*isolate_instructions_buffer == NULL) {
|
||||
Log::PrintErr("Failed to resolve symbol '%s'\n",
|
||||
kIsolateSnapshotInstructionsSymbolName);
|
||||
Platform::Exit(kErrorExitCode);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif // defined(DART_PRECOMPILED_RUNTIME)
|
||||
|
||||
|
||||
static bool ReadAppSnapshot(const char* script_name,
|
||||
const uint8_t** vm_data_buffer,
|
||||
const uint8_t** vm_instructions_buffer,
|
||||
const uint8_t** isolate_data_buffer,
|
||||
const uint8_t** isolate_instructions_buffer) {
|
||||
if (File::GetType(script_name, true) != File::kIsFile) {
|
||||
// If 'script_name' refers to a pipe, don't read to check for an app
|
||||
// snapshot since we cannot rewind if it isn't (and couldn't mmap it in
|
||||
// anyway if it was).
|
||||
return false;
|
||||
}
|
||||
if (ReadAppSnapshotBlobs(script_name, vm_data_buffer, vm_instructions_buffer,
|
||||
isolate_data_buffer, isolate_instructions_buffer)) {
|
||||
return true;
|
||||
}
|
||||
#if defined(DART_PRECOMPILED_RUNTIME)
|
||||
// For testing AOT with the standalone embedder, we also support loading
|
||||
// from a dynamic library to simulate what happens on iOS.
|
||||
return ReadAppSnapshotDynamicLibrary(
|
||||
script_name, vm_data_buffer, vm_instructions_buffer, isolate_data_buffer,
|
||||
isolate_instructions_buffer);
|
||||
#else
|
||||
return false;
|
||||
#endif // defined(DART_PRECOMPILED_RUNTIME)
|
||||
}
|
||||
|
||||
|
||||
static bool WriteInt64(File* file, int64_t size) {
|
||||
return file->WriteFully(&size, sizeof(size));
|
||||
}
|
||||
|
|
|
@ -462,6 +462,7 @@ const int kDoubleSize = sizeof(double); // NOLINT
|
|||
const int kFloatSize = sizeof(float); // NOLINT
|
||||
const int kQuadSize = 4 * kFloatSize;
|
||||
const int kSimd128Size = sizeof(simd128_value_t); // NOLINT
|
||||
const int kInt64Size = sizeof(int64_t); // NOLINT
|
||||
const int kInt32Size = sizeof(int32_t); // NOLINT
|
||||
const int kInt16Size = sizeof(int16_t); // NOLINT
|
||||
#ifdef ARCH_IS_32_BIT
|
||||
|
|
|
@ -154,7 +154,7 @@ class RunKernelTask : public ThreadPool::Task {
|
|||
return false;
|
||||
}
|
||||
ASSERT(!root_library.IsNull());
|
||||
const String& entry_name = String::Handle(Z, String::New("main"));
|
||||
const String& entry_name = String::Handle(Z, String::New("start"));
|
||||
ASSERT(!entry_name.IsNull());
|
||||
const Function& entry = Function::Handle(
|
||||
Z, root_library.LookupFunctionAllowPrivate(entry_name));
|
||||
|
|
16
utils/kernel-service/BUILD.gn
Normal file
16
utils/kernel-service/BUILD.gn
Normal file
|
@ -0,0 +1,16 @@
|
|||
# Copyright (c) 2017, 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("../application_snapshot.gni")
|
||||
|
||||
application_snapshot("kernel-service") {
|
||||
dfe_script = "kernel-service.dart"
|
||||
deps = [
|
||||
"../../runtime/vm:patched_sdk($host_toolchain)",
|
||||
]
|
||||
main_dart = dfe_script
|
||||
training_args = [
|
||||
"file://" + rebase_path("../../pkg/compiler/lib/src/dart2js.dart"),
|
||||
]
|
||||
}
|
|
@ -92,4 +92,26 @@ Future _processLoadRequest(request) async {
|
|||
port.send([tag, inputFileUrl, inputFileUrl, null, result]);
|
||||
}
|
||||
|
||||
main() => new RawReceivePort()..handler = _processLoadRequest;
|
||||
// This entry point is used when running in the kernel isolate.
|
||||
start() => new RawReceivePort()..handler = _processLoadRequest;
|
||||
|
||||
// This entry point is used when creating an app snapshot. The argument provides
|
||||
// a script to compile to warm-up generated code.
|
||||
main(args) {
|
||||
var tag = 1;
|
||||
var scriptUri = args[0];
|
||||
var responsePort = new RawReceivePort();
|
||||
responsePort.handler = (response) {
|
||||
if (response[0] == tag) {
|
||||
// Success.
|
||||
responsePort.close();
|
||||
} else if (response[0] == -tag) {
|
||||
// Compilation error.
|
||||
throw response[4];
|
||||
} else {
|
||||
throw "Unexpected response: $response";
|
||||
}
|
||||
};
|
||||
var request = [tag, responsePort.sendPort, scriptUri];
|
||||
_processLoadRequest(request);
|
||||
}
|
Loading…
Reference in a new issue