01c9c18d24
Change signature of Loader::InitForSnapshot to return an error and check for this error when initializing an isolate. This should fix the flaky crashes reported in https://github.com/dart-lang/sdk/issues/39950 Bug:39950 Change-Id: I564b2f8f924378c156f5bb22238a760be187f8b0 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/130041 Reviewed-by: Alexander Markov <alexmarkov@google.com> Commit-Queue: Siva Annamalai <asiva@google.com>
227 lines
7.7 KiB
C++
227 lines
7.7 KiB
C++
// Copyright (c) 2016, 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.
|
|
|
|
#include "bin/loader.h"
|
|
|
|
#include "bin/builtin.h"
|
|
#include "bin/dartutils.h"
|
|
#include "bin/dfe.h"
|
|
#include "bin/error_exit.h"
|
|
#include "bin/extensions.h"
|
|
#include "bin/file.h"
|
|
#include "bin/gzip.h"
|
|
#include "bin/lockers.h"
|
|
#include "bin/utils.h"
|
|
#include "include/dart_tools_api.h"
|
|
#include "platform/growable_array.h"
|
|
|
|
namespace dart {
|
|
namespace bin {
|
|
|
|
#if !defined(DART_PRECOMPILED_RUNTIME)
|
|
extern DFE dfe;
|
|
#endif
|
|
|
|
Dart_Handle Loader::InitForSnapshot(const char* snapshot_uri,
|
|
IsolateData* isolate_data) {
|
|
ASSERT(isolate_data != NULL);
|
|
|
|
return Loader::Init(isolate_data->packages_file(),
|
|
DartUtils::original_working_directory, snapshot_uri);
|
|
}
|
|
|
|
// Initialize package resolution state.
|
|
Dart_Handle Loader::Init(const char* packages_file,
|
|
const char* working_directory,
|
|
const char* root_script_uri) {
|
|
const int kNumArgs = 3;
|
|
Dart_Handle dart_args[kNumArgs];
|
|
dart_args[0] = (packages_file == NULL)
|
|
? Dart_Null()
|
|
: Dart_NewStringFromCString(packages_file);
|
|
dart_args[1] = Dart_NewStringFromCString(working_directory);
|
|
dart_args[2] = (root_script_uri == NULL)
|
|
? Dart_Null()
|
|
: Dart_NewStringFromCString(root_script_uri);
|
|
return Dart_Invoke(DartUtils::LookupBuiltinLib(),
|
|
DartUtils::NewString("_Init"), kNumArgs, dart_args);
|
|
}
|
|
|
|
static bool PathContainsSeparator(const char* path) {
|
|
return (strchr(path, '/') != NULL) ||
|
|
((strncmp(File::PathSeparator(), "/", 1) != 0) &&
|
|
(strstr(path, File::PathSeparator()) != NULL));
|
|
}
|
|
|
|
#define RETURN_ERROR(result) \
|
|
if (Dart_IsError(result)) return result;
|
|
|
|
Dart_Handle Loader::LoadImportExtension(const char* url_string,
|
|
Dart_Handle library) {
|
|
const char* lib_uri_str = NULL;
|
|
Dart_Handle lib_uri = Dart_LibraryResolvedUrl(library);
|
|
ASSERT(!Dart_IsError(lib_uri));
|
|
Dart_Handle result = Dart_StringToCString(lib_uri, &lib_uri_str);
|
|
RETURN_ERROR(result);
|
|
|
|
UriDecoder decoder(lib_uri_str);
|
|
lib_uri_str = decoder.decoded();
|
|
|
|
if (strncmp(lib_uri_str, "http://", 7) == 0 ||
|
|
strncmp(lib_uri_str, "https://", 8) == 0 ||
|
|
strncmp(lib_uri_str, "data://", 7) == 0) {
|
|
return DartUtils::NewError(
|
|
"Cannot load native extensions over http: or https: or data: %s",
|
|
lib_uri_str);
|
|
}
|
|
|
|
char* lib_path = NULL;
|
|
if (strncmp(lib_uri_str, "file://", 7) == 0) {
|
|
lib_path = DartUtils::DirName(lib_uri_str + 7);
|
|
} else {
|
|
lib_path = strdup(lib_uri_str);
|
|
}
|
|
|
|
const char* path = DartUtils::RemoveScheme(url_string);
|
|
if (!File::IsAbsolutePath(path) && PathContainsSeparator(path)) {
|
|
return DartUtils::NewError(
|
|
"Native extension path must be absolute, or simply the file name: %s",
|
|
path);
|
|
}
|
|
|
|
result = Extensions::LoadExtension(lib_path, path, library);
|
|
free(lib_path);
|
|
return result;
|
|
}
|
|
|
|
Dart_Handle Loader::ReloadNativeExtensions() {
|
|
Dart_Handle scheme =
|
|
Dart_NewStringFromCString(DartUtils::kDartExtensionScheme);
|
|
Dart_Handle extension_imports = Dart_GetImportsOfScheme(scheme);
|
|
RETURN_ERROR(extension_imports);
|
|
|
|
intptr_t length = -1;
|
|
Dart_Handle result = Dart_ListLength(extension_imports, &length);
|
|
RETURN_ERROR(result);
|
|
Dart_Handle* import_handles = reinterpret_cast<Dart_Handle*>(
|
|
Dart_ScopeAllocate(sizeof(Dart_Handle) * length));
|
|
result = Dart_ListGetRange(extension_imports, 0, length, import_handles);
|
|
RETURN_ERROR(result);
|
|
for (intptr_t i = 0; i < length; i += 2) {
|
|
Dart_Handle importer = import_handles[i];
|
|
Dart_Handle importee = import_handles[i + 1];
|
|
|
|
const char* extension_uri = NULL;
|
|
result = Dart_StringToCString(Dart_LibraryUrl(importee), &extension_uri);
|
|
RETURN_ERROR(result);
|
|
const char* extension_path = DartUtils::RemoveScheme(extension_uri);
|
|
|
|
const char* lib_uri = NULL;
|
|
result = Dart_StringToCString(Dart_LibraryUrl(importer), &lib_uri);
|
|
RETURN_ERROR(result);
|
|
|
|
char* lib_path = NULL;
|
|
if (strncmp(lib_uri, "file://", 7) == 0) {
|
|
lib_path = DartUtils::DirName(DartUtils::RemoveScheme(lib_uri));
|
|
} else {
|
|
lib_path = strdup(lib_uri);
|
|
}
|
|
|
|
result = Extensions::LoadExtension(lib_path, extension_path, importer);
|
|
free(lib_path);
|
|
RETURN_ERROR(result);
|
|
}
|
|
|
|
return Dart_True();
|
|
}
|
|
|
|
#if defined(DART_PRECOMPILED_RUNTIME)
|
|
Dart_Handle Loader::LibraryTagHandler(Dart_LibraryTag tag,
|
|
Dart_Handle library,
|
|
Dart_Handle url) {
|
|
return Dart_Null();
|
|
}
|
|
#else
|
|
static void MallocFinalizer(void* isolate_callback_data,
|
|
Dart_WeakPersistentHandle handle,
|
|
void* peer) {
|
|
free(peer);
|
|
}
|
|
|
|
Dart_Handle Loader::LibraryTagHandler(Dart_LibraryTag tag,
|
|
Dart_Handle library,
|
|
Dart_Handle url) {
|
|
const char* url_string = NULL;
|
|
Dart_Handle result = Dart_StringToCString(url, &url_string);
|
|
if (Dart_IsError(result)) {
|
|
return result;
|
|
}
|
|
if (tag == Dart_kCanonicalizeUrl) {
|
|
Dart_Handle library_url = Dart_LibraryUrl(library);
|
|
if (Dart_IsError(library_url)) {
|
|
return library_url;
|
|
}
|
|
const char* library_url_string = NULL;
|
|
result = Dart_StringToCString(library_url, &library_url_string);
|
|
if (Dart_IsError(result)) {
|
|
return result;
|
|
}
|
|
bool is_dart_scheme_url = DartUtils::IsDartSchemeURL(url_string);
|
|
bool is_dart_library = DartUtils::IsDartSchemeURL(library_url_string);
|
|
if (is_dart_scheme_url || is_dart_library) {
|
|
return url;
|
|
}
|
|
return Dart_DefaultCanonicalizeUrl(library_url, url);
|
|
}
|
|
if (tag == Dart_kKernelTag) {
|
|
uint8_t* kernel_buffer = NULL;
|
|
intptr_t kernel_buffer_size = 0;
|
|
if (!DFE::TryReadKernelFile(url_string, &kernel_buffer,
|
|
&kernel_buffer_size)) {
|
|
return DartUtils::NewError("'%s' is not a kernel file", url_string);
|
|
}
|
|
result = Dart_NewExternalTypedData(Dart_TypedData_kUint8, kernel_buffer,
|
|
kernel_buffer_size);
|
|
Dart_NewWeakPersistentHandle(result, kernel_buffer, kernel_buffer_size,
|
|
MallocFinalizer);
|
|
return result;
|
|
}
|
|
if (tag == Dart_kImportExtensionTag) {
|
|
if (!DartUtils::IsDartExtensionSchemeURL(url_string)) {
|
|
return DartUtils::NewError(
|
|
"Native extensions must use the dart-ext: scheme : %s", url_string);
|
|
}
|
|
return Loader::LoadImportExtension(url_string, library);
|
|
}
|
|
if (dfe.CanUseDartFrontend() && dfe.UseDartFrontend() &&
|
|
(tag == Dart_kImportTag)) {
|
|
// E.g., IsolateMirror.loadUri.
|
|
char* error = NULL;
|
|
int exit_code = 0;
|
|
uint8_t* kernel_buffer = NULL;
|
|
intptr_t kernel_buffer_size = -1;
|
|
dfe.CompileAndReadScript(url_string, &kernel_buffer, &kernel_buffer_size,
|
|
&error, &exit_code, NULL);
|
|
if (exit_code == 0) {
|
|
return Dart_LoadLibraryFromKernel(kernel_buffer, kernel_buffer_size);
|
|
} else if (exit_code == kCompilationErrorExitCode) {
|
|
Dart_Handle result = Dart_NewCompilationError(error);
|
|
free(error);
|
|
return result;
|
|
} else {
|
|
Dart_Handle result = Dart_NewApiError(error);
|
|
free(error);
|
|
return result;
|
|
}
|
|
}
|
|
return DartUtils::NewError("Invalid tag : %d '%s'", tag, url_string);
|
|
}
|
|
#endif // !defined(DART_PRECOMPILED_RUNTIME)
|
|
|
|
void Loader::InitOnce() {
|
|
}
|
|
|
|
} // namespace bin
|
|
} // namespace dart
|