| // Copyright 2016 The Fuchsia 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 "dart-pkg/fuchsia/sdk_ext/fuchsia.h" |
| |
| #include <zircon/syscalls.h> |
| |
| #include <stdio.h> |
| #include <string.h> |
| |
| #include <memory> |
| #include <vector> |
| |
| #include "dart-pkg/zircon/sdk_ext/handle.h" |
| #include "dart-pkg/zircon/sdk_ext/natives.h" |
| #include "dart-pkg/zircon/sdk_ext/system.h" |
| #include "src/lib/fxl/arraysize.h" |
| #include "src/lib/fxl/logging.h" |
| #include "src/lib/fxl/macros.h" |
| #include "third_party/dart/runtime/include/dart_api.h" |
| #include "third_party/tonic/dart_binding_macros.h" |
| #include "third_party/tonic/dart_class_library.h" |
| #include "third_party/tonic/dart_class_provider.h" |
| #include "third_party/tonic/dart_library_natives.h" |
| #include "third_party/tonic/dart_state.h" |
| #include "third_party/tonic/logging/dart_invoke.h" |
| #include "third_party/tonic/typed_data/uint8_list.h" |
| |
| using tonic::ToDart; |
| |
| namespace fuchsia { |
| namespace dart { |
| namespace { |
| |
| static tonic::DartLibraryNatives* g_natives; |
| |
| tonic::DartLibraryNatives* InitNatives() { |
| tonic::DartLibraryNatives* natives = new tonic::DartLibraryNatives(); |
| |
| return natives; |
| } |
| |
| #define REGISTER_FUNCTION(name, count) {"" #name, name, count}, |
| #define DECLARE_FUNCTION(name, count) \ |
| extern void name(Dart_NativeArguments args); |
| |
| #define FIDL_NATIVE_LIST(V) V(SetReturnCode, 1) |
| |
| FIDL_NATIVE_LIST(DECLARE_FUNCTION); |
| |
| static struct NativeEntries { |
| const char* name; |
| Dart_NativeFunction function; |
| int argument_count; |
| } Entries[] = {FIDL_NATIVE_LIST(REGISTER_FUNCTION)}; |
| |
| Dart_NativeFunction NativeLookup(Dart_Handle name, int argument_count, |
| bool* auto_setup_scope) { |
| const char* function_name = nullptr; |
| Dart_Handle result = Dart_StringToCString(name, &function_name); |
| if (Dart_IsError(result)) { |
| Dart_PropagateError(result); |
| } |
| FXL_DCHECK(function_name != nullptr); |
| FXL_DCHECK(auto_setup_scope != nullptr); |
| *auto_setup_scope = true; |
| size_t num_entries = arraysize(Entries); |
| for (size_t i = 0; i < num_entries; ++i) { |
| const struct NativeEntries& entry = Entries[i]; |
| if (!strcmp(function_name, entry.name) && |
| (entry.argument_count == argument_count)) { |
| return entry.function; |
| } |
| } |
| if (!g_natives) |
| g_natives = InitNatives(); |
| return g_natives->GetNativeFunction(name, argument_count, auto_setup_scope); |
| } |
| |
| const uint8_t* NativeSymbol(Dart_NativeFunction native_function) { |
| size_t num_entries = arraysize(Entries); |
| for (size_t i = 0; i < num_entries; ++i) { |
| const struct NativeEntries& entry = Entries[i]; |
| if (entry.function == native_function) { |
| return reinterpret_cast<const uint8_t*>(entry.name); |
| } |
| } |
| if (!g_natives) |
| g_natives = InitNatives(); |
| return g_natives->GetSymbol(native_function); |
| } |
| |
| void SetReturnCode(Dart_NativeArguments arguments) { |
| int64_t return_code; |
| Dart_Handle status = |
| Dart_GetNativeIntegerArgument(arguments, 0, &return_code); |
| if (!tonic::LogIfError(status)) { |
| tonic::DartState::Current()->SetReturnCode(return_code); |
| } |
| } |
| |
| } // namespace |
| |
| void Initialize(fidl::InterfaceHandle<fuchsia::sys::Environment> environment, |
| zx::channel directory_request) { |
| zircon::dart::Initialize(); |
| |
| Dart_Handle library = Dart_LookupLibrary(ToDart("dart:fuchsia")); |
| FXL_CHECK(!tonic::LogIfError(library)); |
| Dart_Handle result = Dart_SetNativeResolver( |
| library, fuchsia::dart::NativeLookup, fuchsia::dart::NativeSymbol); |
| FXL_CHECK(!tonic::LogIfError(result)); |
| |
| auto dart_state = tonic::DartState::Current(); |
| std::unique_ptr<tonic::DartClassProvider> fuchsia_class_provider( |
| new tonic::DartClassProvider(dart_state, "dart:fuchsia")); |
| dart_state->class_library().add_provider("fuchsia", |
| std::move(fuchsia_class_provider)); |
| |
| result = Dart_SetField( |
| library, ToDart("_environment"), |
| ToDart(zircon::dart::Handle::Create(environment.TakeChannel()))); |
| FXL_CHECK(!tonic::LogIfError(result)); |
| |
| if (directory_request) { |
| result = Dart_SetField( |
| library, ToDart("_outgoingServices"), |
| ToDart(zircon::dart::Handle::Create(std::move(directory_request)))); |
| FXL_CHECK(!tonic::LogIfError(result)); |
| } |
| } |
| |
| } // namespace dart |
| } // namespace fuchsia |