flutter_flutter/runtime/dart_service_isolate.cc
Alexander Aprelev f5c7cb366a Roll dart to b298fc6d8f6a0e1aa841dbbdda26663d6012a79a. (#5155)
* Roll dart to b298fc6d8f6a0e1aa841dbbdda26663d6012a79a.

Changes since last roll:
```
b298fc6d8f Revert "[kernel] Change dill representation of doubles"
9a7e1f64a2 Revert "Revert "Fix incorrect handling of NSM forwarders and pull all logic into CFE.""
cbca4006f8 fix #30907, add library constants for all SDK libraries
61c226b4ea Only create Goma's analyzer on Linux.
24dd9b4176 Revert "Fix incorrect handling of NSM forwarders and pull all logic into CFE."
bed71b7776 Migrate and clean up the prefix negative tests.
1fcd896ed9 [VM] Avoid deadlock by allowing us to run kernel isolate from a script snapshot, fixes all dartk-sim* builders
0bc6e7217a Update expression compilation expectations.
9038b8f45f CFE support for compiling individual expressions in a context.
7d5025e814 Fix incorrect handling of NSM forwarders and pull all logic into CFE.
e2247e5e00 Put the '@' outside the revision variables.
9381424204 Fix presubmit on Windows. Dart executable is not called .bat
2a8c3515b2 Avoid strong+checked mode: strong mode supersedes checked mode
b7698dcbce Update status for Windows
8baa82413b [infra] Remove --no-preview-dart-2 flag from gardening tools
47e9039512 Don't encode strings up front; don't toString uris
4a0ac85cc3 Update co19 status
ce7329849d Fix build breakages - use platform independent path specification is test so that   it works on windows - skip test for precompiled and dartk builds as the test uses   spawnUri which is not supported in these modes
ee6351a147 [VM] Set up package config value when invoking the front end for compilation, this should fix issue 32950 "(Isolate.spawnUri() ignores packageConfig argument in Dart 2 mode.'
d1286a367e Strong mode update for swarm
fd27cc3435 Don't store bytes in the file cache.
73abd61304 Re-land "Clean up the use of deprecated API in the analyzer_plugin package".
607f4f5769 [vm] Get more helpful errors from Dart_SetVMFlags and Dart_MakeIsolateRunnable.
f044637c8b [infra] Upgrade checked in SDKs to 2.0.0-dev.52.0
dcf10816aa [infra] Add script that updates checked in SDKs
f8bea2a7e6 dart2js: Register inlined native methods for dump info
7fe8659613 dump-info: Use relative paths for library canonicalUri...
dcf4886500 [frontend-server] Add verbose option.
5087ffa481 [release] Move DDC sync-async flip to correct section in the release notes
fe7056ebaa [release] Update changelog for 2.0.0-dev.52.0
```

* Pick up another revert to fix https://github.com/flutter/flutter/issues/17214 and few more dart commits landed since:

```
4c9b712052 Revert "Don't encode strings up front; don't toString uris"
a1fbf62742 [build] Place 'extern "C"' before __attribute__, as required by gcc.
258c5172df [vm] Remove dart_mirrors_api.h.
384c55c29e Update dartdoc & dependencies to v0.19.0.
```

* fix licenses
2018-05-02 18:42:14 -07:00

289 lines
9.7 KiB
C++

// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "flutter/runtime/dart_service_isolate.h"
#include <string.h>
#include "flutter/runtime/embedder_resources.h"
#include "lib/fxl/logging.h"
#include "lib/tonic/converter/dart_converter.h"
#include "lib/tonic/dart_library_natives.h"
#include "lib/tonic/logging/dart_error.h"
#include "third_party/dart/runtime/include/dart_api.h"
#define RETURN_ERROR_HANDLE(handle) \
if (Dart_IsError(handle)) { \
return handle; \
}
#define SHUTDOWN_ON_ERROR(handle) \
if (Dart_IsError(handle)) { \
*error = strdup(Dart_GetError(handle)); \
Dart_ExitScope(); \
Dart_ShutdownIsolate(); \
return false; \
}
#define kLibrarySourceNamePrefix "/vmservice"
static const char* kServiceIsolateScript = "vmservice_io.dart";
namespace flutter {
namespace runtime {
extern ResourcesEntry __flutter_embedded_service_isolate_resources_[];
}
} // namespace flutter
namespace blink {
namespace {
static Dart_LibraryTagHandler g_embedder_tag_handler;
static tonic::DartLibraryNatives* g_natives;
static EmbedderResources* g_resources;
static std::string observatory_uri_;
Dart_NativeFunction GetNativeFunction(Dart_Handle name,
int argument_count,
bool* auto_setup_scope) {
FXL_CHECK(g_natives);
return g_natives->GetNativeFunction(name, argument_count, auto_setup_scope);
}
const uint8_t* GetSymbol(Dart_NativeFunction native_function) {
FXL_CHECK(g_natives);
return g_natives->GetSymbol(native_function);
}
} // namespace
void DartServiceIsolate::TriggerResourceLoad(Dart_NativeArguments args) {
Dart_Handle library = Dart_RootLibrary();
FXL_DCHECK(!Dart_IsError(library));
Dart_Handle result = LoadResources(library);
FXL_DCHECK(!Dart_IsError(result));
}
void DartServiceIsolate::NotifyServerState(Dart_NativeArguments args) {
Dart_Handle exception = nullptr;
std::string uri =
tonic::DartConverter<std::string>::FromArguments(args, 0, exception);
if (!exception) {
observatory_uri_ = uri;
}
}
std::string DartServiceIsolate::GetObservatoryUri() {
return observatory_uri_;
}
void DartServiceIsolate::Shutdown(Dart_NativeArguments args) {
// NO-OP.
}
bool DartServiceIsolate::Startup(std::string server_ip,
intptr_t server_port,
Dart_LibraryTagHandler embedder_tag_handler,
bool running_from_sources,
bool disable_origin_check,
char** error) {
Dart_Isolate isolate = Dart_CurrentIsolate();
FXL_CHECK(isolate);
// Remember the embedder's library tag handler.
g_embedder_tag_handler = embedder_tag_handler;
FXL_CHECK(g_embedder_tag_handler);
// Setup native entries.
if (!g_natives) {
g_natives = new tonic::DartLibraryNatives();
g_natives->Register({
{"VMServiceIO_NotifyServerState", NotifyServerState, 1, true},
{"VMServiceIO_Shutdown", Shutdown, 0, true},
});
}
if (!g_resources) {
g_resources = new EmbedderResources(
&flutter::runtime::__flutter_embedded_service_isolate_resources_[0]);
}
Dart_Handle result;
if (running_from_sources) {
// Use our own library tag handler when loading service isolate sources.
Dart_SetLibraryTagHandler(DartServiceIsolate::LibraryTagHandler);
// Load main script.
Dart_Handle library = LoadScript(kServiceIsolateScript);
FXL_DCHECK(library != Dart_Null());
SHUTDOWN_ON_ERROR(library);
// Setup native entry resolution.
result = Dart_SetNativeResolver(library, GetNativeFunction, GetSymbol);
SHUTDOWN_ON_ERROR(result);
// Finalize loading.
result = Dart_FinalizeLoading(false);
SHUTDOWN_ON_ERROR(result);
} else {
Dart_Handle uri = Dart_NewStringFromCString("dart:vmservice_io");
Dart_Handle library = Dart_LookupLibrary(uri);
SHUTDOWN_ON_ERROR(library);
result = Dart_SetRootLibrary(library);
SHUTDOWN_ON_ERROR(result);
result = Dart_SetNativeResolver(library, GetNativeFunction, GetSymbol);
SHUTDOWN_ON_ERROR(result);
}
// Make runnable.
Dart_ExitScope();
Dart_ExitIsolate();
*error = Dart_IsolateMakeRunnable(isolate);
if (*error) {
Dart_EnterIsolate(isolate);
Dart_ShutdownIsolate();
return false;
}
Dart_EnterIsolate(isolate);
Dart_EnterScope();
Dart_Handle library = Dart_RootLibrary();
SHUTDOWN_ON_ERROR(library);
// Set the HTTP server's ip.
result = Dart_SetField(library, Dart_NewStringFromCString("_ip"),
Dart_NewStringFromCString(server_ip.c_str()));
SHUTDOWN_ON_ERROR(result);
// If we have a port specified, start the server immediately.
bool auto_start = server_port >= 0;
if (server_port < 0) {
// Adjust server_port to port 0 which will result in the first available
// port when the HTTP server is started.
server_port = 0;
}
// Set the HTTP's servers port.
result = Dart_SetField(library, Dart_NewStringFromCString("_port"),
Dart_NewInteger(server_port));
SHUTDOWN_ON_ERROR(result);
result = Dart_SetField(library, Dart_NewStringFromCString("_autoStart"),
Dart_NewBoolean(auto_start));
SHUTDOWN_ON_ERROR(result);
result =
Dart_SetField(library, Dart_NewStringFromCString("_originCheckDisabled"),
Dart_NewBoolean(disable_origin_check));
SHUTDOWN_ON_ERROR(result);
return true;
}
Dart_Handle DartServiceIsolate::GetSource(const char* name) {
const intptr_t kBufferSize = 512;
char buffer[kBufferSize];
snprintf(&buffer[0], kBufferSize - 1, "%s/%s", kLibrarySourceNamePrefix,
name);
const char* vmservice_source = NULL;
int r = g_resources->ResourceLookup(buffer, &vmservice_source);
FXL_DCHECK(r != EmbedderResources::kNoSuchInstance);
return Dart_NewStringFromCString(vmservice_source);
}
Dart_Handle DartServiceIsolate::LoadScript(const char* name) {
Dart_Handle url = Dart_NewStringFromCString("dart:vmservice_io");
Dart_Handle source = GetSource(name);
return Dart_LoadScript(url, Dart_Null(), source, 0, 0);
}
Dart_Handle DartServiceIsolate::LoadSource(Dart_Handle library,
const char* name) {
Dart_Handle url = Dart_NewStringFromCString(name);
Dart_Handle source = GetSource(name);
return Dart_LoadSource(library, url, Dart_Null(), source, 0, 0);
}
Dart_Handle DartServiceIsolate::LoadResource(Dart_Handle library,
const char* resource_name) {
// Prepare for invoke call.
Dart_Handle name = Dart_NewStringFromCString(resource_name);
RETURN_ERROR_HANDLE(name);
const char* data_buffer = NULL;
int data_buffer_length =
g_resources->ResourceLookup(resource_name, &data_buffer);
FXL_DCHECK(data_buffer_length != EmbedderResources::kNoSuchInstance);
Dart_Handle data_list =
Dart_NewTypedData(Dart_TypedData_kUint8, data_buffer_length);
RETURN_ERROR_HANDLE(data_list);
Dart_TypedData_Type type = Dart_TypedData_kInvalid;
void* data_list_buffer = NULL;
intptr_t data_list_buffer_length = 0;
Dart_Handle result = Dart_TypedDataAcquireData(
data_list, &type, &data_list_buffer, &data_list_buffer_length);
RETURN_ERROR_HANDLE(result);
FXL_DCHECK(data_buffer_length == data_list_buffer_length);
FXL_DCHECK(data_list_buffer != NULL);
FXL_DCHECK(type = Dart_TypedData_kUint8);
memmove(data_list_buffer, &data_buffer[0], data_buffer_length);
result = Dart_TypedDataReleaseData(data_list);
RETURN_ERROR_HANDLE(result);
// Make invoke call.
const intptr_t kNumArgs = 2;
Dart_Handle args[kNumArgs] = {name, data_list};
result = Dart_Invoke(library, Dart_NewStringFromCString("_addResource"),
kNumArgs, args);
return result;
}
Dart_Handle DartServiceIsolate::LoadResources(Dart_Handle library) {
Dart_Handle result = Dart_Null();
intptr_t prefixLen = strlen(kLibrarySourceNamePrefix);
for (intptr_t i = 0; g_resources->Path(i) != NULL; i++) {
const char* path = g_resources->Path(i);
// If it doesn't begin with kLibrarySourceNamePrefix it is a frontend
// resource.
if (strncmp(path, kLibrarySourceNamePrefix, prefixLen) != 0) {
result = LoadResource(library, path);
if (Dart_IsError(result)) {
break;
}
}
}
return result;
}
Dart_Handle DartServiceIsolate::LibraryTagHandler(Dart_LibraryTag tag,
Dart_Handle library,
Dart_Handle url) {
if (!Dart_IsLibrary(library)) {
return Dart_NewApiError("not a library");
}
if (!Dart_IsString(url)) {
return Dart_NewApiError("url is not a string");
}
const char* url_string = NULL;
Dart_Handle result = Dart_StringToCString(url, &url_string);
if (Dart_IsError(result)) {
return result;
}
Dart_Handle library_url = Dart_LibraryUrl(library);
const char* library_url_string = NULL;
result = Dart_StringToCString(library_url, &library_url_string);
if (Dart_IsError(result)) {
return result;
}
if (tag == Dart_kImportTag) {
// Embedder handles all requests for external libraries.
return g_embedder_tag_handler(tag, library, url);
}
FXL_DCHECK((tag == Dart_kSourceTag) || (tag == Dart_kCanonicalizeUrl));
if (tag == Dart_kCanonicalizeUrl) {
// url is already canonicalized.
return url;
}
// Get source from builtin resources.
Dart_Handle source = GetSource(url_string);
if (Dart_IsError(source)) {
return source;
}
return Dart_LoadSource(library, url, Dart_Null(), source, 0, 0);
}
} // namespace blink