[vm] Remove support for dart-ext: imports

Per breaking change #45451 we are removing support for dart-ext:
style native extensions from the Dart VM.

This CL removes the associated VM code, tests and samples. It also ports
a single test which used dart-ext: import to use FFI instead.

TEST=ci

Bug: https://github.com/dart-lang/sdk/issues/45451
Change-Id: Iae984bce32baf29a950b5de1323939006a217b94
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/212050
Commit-Queue: Slava Egorov <vegorov@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
This commit is contained in:
Vyacheslav Egorov 2021-09-02 14:14:35 +00:00 committed by commit-bot@chromium.org
parent 6050b7e06f
commit bda70c8489
70 changed files with 221 additions and 2743 deletions

View file

@ -29,7 +29,6 @@ group("most") {
":dartanalyzer",
":dartdevc",
":runtime",
":samples",
]
}
@ -42,13 +41,11 @@ group("runtime") {
}
deps = [
"runtime/bin:dart",
"runtime/bin:entrypoints_verification_test_extension",
"runtime/bin:entrypoints_verification_test",
"runtime/bin:ffi_test_dynamic_library",
"runtime/bin:ffi_test_functions",
"runtime/bin:process_test",
"runtime/bin:run_vm_tests",
"runtime/bin:sample_extension",
"runtime/bin:test_extension",
"runtime/vm:kernel_platform_files($host_toolchain)",
"utils/kernel-service:kernel-service",
]
@ -118,10 +115,6 @@ group("dart2js_bot") {
deps = [ ":create_sdk" ]
}
group("samples") {
deps = [ "runtime/bin:sample_extension" ]
}
# This rule and the compressed_observatory_archive rule are for the Fuchsia
# bots that pre-build the Observatory. They copy the observatory tar files to
# the root build output directory for convenient access by the Fuchsia buildbot

View file

@ -80,6 +80,12 @@
`dart compile exe` and `dart compile aot-snapshot` commands, which offer the
same functionality.
#### Dart VM
- **Breaking Change** [#45451][]: Support for `dart-ext:`-style native
extensions has been removed as previously announced. Use `dart:ffi` to bind
to native libraries instead.
## 2.14.0
### Language

View file

@ -977,9 +977,9 @@ executable("run_vm_tests") {
}
}
shared_library("test_extension") {
shared_library("entrypoints_verification_test") {
deps = [ ":dart" ]
sources = [ "test_extension.c" ]
sources = [ "entrypoints_verification_test.cc" ]
include_dirs = [ ".." ]
defines = [
# The only effect of DART_SHARED_LIB is to export the Dart API.
@ -989,26 +989,7 @@ shared_library("test_extension") {
cflags = [ "-fPIC" ]
}
if (is_win) {
sources += [ "test_extension_dllmain_win.cc" ]
libs = [ "dart.lib" ]
abs_root_out_dir = rebase_path(root_out_dir)
ldflags = [ "/LIBPATH:$abs_root_out_dir" ]
}
}
shared_library("entrypoints_verification_test_extension") {
deps = [ ":dart" ]
sources = [ "entrypoints_verification_test_extension.cc" ]
include_dirs = [ ".." ]
defines = [
# The only effect of DART_SHARED_LIB is to export the Dart API.
"DART_SHARED_LIB",
]
if (is_linux || is_android) {
cflags = [ "-fPIC" ]
}
if (is_win) {
sources += [ "entrypoints_verification_test_extension_dllmain_win.cc" ]
# TODO(dartbug.com/40579): This wrongly links in dart.exe on precompiled.
libs = [ "dart.lib" ]
abs_root_out_dir = rebase_path(root_out_dir)
ldflags = [ "/LIBPATH:$abs_root_out_dir" ]
@ -1070,26 +1051,6 @@ shared_library("ffi_test_functions") {
}
}
shared_library("sample_extension") {
deps = [ ":dart" ]
sources = [ "../../samples/sample_extension/sample_extension.cc" ]
include_dirs = [ ".." ]
defines = [
# The only effect of DART_SHARED_LIB is to export the Dart API.
"DART_SHARED_LIB",
]
if (is_linux || is_android) {
cflags = [ "-fPIC" ]
}
if (is_win) {
sources +=
[ "../../samples/sample_extension/sample_extension_dllmain_win.cc" ]
libs = [ "dart.lib" ]
abs_root_out_dir = rebase_path(root_out_dir)
ldflags = [ "/LIBPATH:$abs_root_out_dir" ]
}
}
# DartLibFuzzer only "exists" for restricted configurations.
if (defined(is_linux) && is_linux && defined(is_asan) && is_asan &&
(dart_target_arch == "x64" || dart_target_arch == "arm64")) {

View file

@ -25,13 +25,6 @@ builtin_impl_sources = [
"directory_win.cc",
"exe_utils.cc",
"exe_utils.h",
"extensions.cc",
"extensions.h",
"extensions_android.cc",
"extensions_fuchsia.cc",
"extensions_linux.cc",
"extensions_macos.cc",
"extensions_win.cc",
"fdutils.h",
"fdutils_android.cc",
"fdutils_fuchsia.cc",

View file

@ -6,7 +6,6 @@
#include "bin/crypto.h"
#include "bin/directory.h"
#include "bin/extensions.h"
#include "bin/file.h"
#include "bin/io_buffer.h"
#include "bin/namespace.h"
@ -34,7 +33,6 @@ namespace bin {
const char* DartUtils::original_working_directory = NULL;
const char* const DartUtils::kDartScheme = "dart:";
const char* const DartUtils::kDartExtensionScheme = "dart-ext:";
const char* const DartUtils::kAsyncLibURL = "dart:async";
const char* const DartUtils::kBuiltinLibURL = "dart:_builtin";
const char* const DartUtils::kCoreLibURL = "dart:core";
@ -227,14 +225,6 @@ bool DartUtils::IsHttpSchemeURL(const char* url_name) {
return (strncmp(url_name, kHttpScheme, kHttpSchemeLen) == 0);
}
bool DartUtils::IsDartExtensionSchemeURL(const char* url_name) {
static const intptr_t kDartExtensionSchemeLen = strlen(kDartExtensionScheme);
// If the URL starts with "dart-ext:" then it is considered as a special
// extension library URL which is handled differently from other URLs.
return (strncmp(url_name, kDartExtensionScheme, kDartExtensionSchemeLen) ==
0);
}
bool DartUtils::IsDartIOLibURL(const char* url_name) {
return (strcmp(url_name, kIOLibURL) == 0);
}

View file

@ -146,7 +146,6 @@ class DartUtils {
const char* name,
const char* val);
static bool IsDartSchemeURL(const char* url_name);
static bool IsDartExtensionSchemeURL(const char* url_name);
static bool IsDartIOLibURL(const char* url_name);
static bool IsDartCLILibURL(const char* url_name);
static bool IsDartHttpLibURL(const char* url_name);
@ -253,7 +252,6 @@ class DartUtils {
static const char* original_working_directory;
static const char* const kDartScheme;
static const char* const kDartExtensionScheme;
static const char* const kAsyncLibURL;
static const char* const kBuiltinLibURL;
static const char* const kCoreLibURL;

View file

@ -5,8 +5,12 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "./include/dart_api.h"
#include "./include/dart_native_api.h"
// TODO(dartbug.com/40579): This requires static linking to either link
// dart.exe or dart_precompiled_runtime.exe on Windows.
// The sample currently fails on Windows in AOT mode.
#include "include/dart_api.h"
#include "include/dart_native_api.h"
#define CHECK(H) \
do { \
@ -25,12 +29,12 @@
abort(); \
}
bool isDartPrecompiledRuntime = true;
static bool is_dart_precompiled_runtime = true;
// Some invalid accesses are allowed in AOT since we don't retain @pragma
// annotations. Therefore we skip the negative tests in AOT.
#define FAIL(name, result) \
if (!isDartPrecompiledRuntime) { \
if (!is_dart_precompiled_runtime) { \
Fail(name, result); \
}
@ -42,25 +46,25 @@ void Fail(const char* name, Dart_Handle result) {
}
#define FAIL_INVOKE_FIELD(name, result) \
if (!isDartPrecompiledRuntime) { \
if (!is_dart_precompiled_runtime) { \
FailInvokeField(name, result); \
}
void FailInvokeField(const char* name, Dart_Handle result) {
static void FailInvokeField(const char* name, Dart_Handle result) {
ASSERT(Dart_IsApiError(result));
const char* error = Dart_GetError(result);
ASSERT(strstr(error, name));
ASSERT(strstr(error, "Entry-points do not allow invoking fields"));
}
void FailClosurizeConstructor(const char* name, Dart_Handle result) {
static void FailClosurizeConstructor(const char* name, Dart_Handle result) {
ASSERT(Dart_IsUnhandledExceptionError(result));
const char* error = Dart_GetError(result);
ASSERT(strstr(error, name));
ASSERT(strstr(error, "No static getter"));
}
void TestFields(Dart_Handle target) {
static void TestFields(Dart_Handle target) {
FAIL("fld0", Dart_GetField(target, Dart_NewStringFromCString("fld0")));
FAIL("fld0",
Dart_SetField(target, Dart_NewStringFromCString("fld0"), Dart_Null()));
@ -89,7 +93,9 @@ void TestFields(Dart_Handle target) {
Dart_Invoke(target, Dart_NewStringFromCString("fld3"), 0, nullptr));
}
void RunTests(Dart_NativeArguments arguments) {
DART_EXPORT void RunTests() {
is_dart_precompiled_runtime = Dart_IsPrecompiledRuntime();
Dart_Handle lib = Dart_RootLibrary();
//////// Test allocation and constructor invocation.
@ -165,30 +171,3 @@ void RunTests(Dart_NativeArguments arguments) {
TestFields(lib);
}
Dart_NativeFunction ResolveName(Dart_Handle name,
int argc,
bool* auto_setup_scope) {
if (auto_setup_scope == NULL) {
return NULL;
}
*auto_setup_scope = true;
return RunTests;
}
DART_EXPORT Dart_Handle
entrypoints_verification_test_extension_Init(Dart_Handle parent_library) {
isDartPrecompiledRuntime = Dart_IsPrecompiledRuntime();
if (Dart_IsError(parent_library)) {
return parent_library;
}
Dart_Handle result_code =
Dart_SetNativeResolver(parent_library, ResolveName, NULL);
if (Dart_IsError(result_code)) {
return result_code;
}
return Dart_Null();
}

View file

@ -1,15 +0,0 @@
// Copyright (c) 2019, 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 "platform/globals.h"
#if defined(DART_HOST_OS_WINDOWS)
#define WIN32_LEAN_AND_MEAN
#include <windows.h> // NOLINT
BOOL APIENTRY DllMain(HMODULE module, DWORD reason, LPVOID reserved) {
return true;
}
#endif // defined(DART_HOST_OS_WINDOWS)

View file

@ -1,141 +0,0 @@
// Copyright (c) 2012, 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/extensions.h"
#include <stdio.h>
#include "bin/dartutils.h"
#include "bin/file.h"
#include "bin/platform.h"
#include "bin/utils.h"
#include "include/dart_api.h"
#include "platform/assert.h"
#include "platform/globals.h"
#include "platform/utils.h"
namespace dart {
namespace bin {
static char PathSeparator() {
const char* sep = File::PathSeparator();
ASSERT(strlen(sep) == 1);
return sep[0];
}
void* Extensions::MakePathAndResolve(const char* dir, const char* name) {
// First try to find the library with a suffix specifying the architecture.
{
const char* path_components[] = {
dir,
Platform::LibraryPrefix(),
name,
"-",
Platform::HostArchitecture(), // arm
".",
Platform::LibraryExtension(), // so
NULL,
};
const char* library_file = Concatenate(path_components);
void* library_handle = LoadExtensionLibrary(library_file);
if (library_handle != NULL) {
return library_handle;
}
}
// Fall back on a library name without the suffix.
{
const char* path_components[] = {
dir,
Platform::LibraryPrefix(),
name,
".",
Platform::LibraryExtension(), // so
NULL,
};
const char* library_file = Concatenate(path_components);
return LoadExtensionLibrary(library_file);
}
}
// IMPORTANT: In the absolute path case, do not extract the filename and search
// for that by passing it to LoadLibrary. That can lead to confusion in
// which the absolute path is wrong, and a different version of the library is
// loaded from the standard location.
void* Extensions::ResolveAbsPathExtension(const char* extension_path) {
const char* last_slash = strrchr(extension_path, PathSeparator()) + 1;
char* name = Utils::StrDup(last_slash);
char* dir = Utils::StrNDup(extension_path, last_slash - extension_path);
void* library_handle = MakePathAndResolve(dir, name);
free(dir);
free(name);
return library_handle;
}
void* Extensions::ResolveExtension(const char* extension_directory,
const char* extension_name) {
// If the path following dart-ext is an absolute path, then only look for the
// library there.
if (File::IsAbsolutePath(extension_name)) {
return ResolveAbsPathExtension(extension_name);
}
// If the path following dart-ext is just a file name, first look next to
// the importing Dart library.
void* library_handle =
MakePathAndResolve(extension_directory, extension_name);
if (library_handle != NULL) {
return library_handle;
}
// Then pass the library name down to the platform. E.g. dlopen will do its
// own search in standard search locations.
return MakePathAndResolve("", extension_name);
}
Dart_Handle Extensions::LoadExtension(const char* extension_directory,
const char* extension_name,
Dart_Handle parent_library) {
void* library_handle = ResolveExtension(extension_directory, extension_name);
if (library_handle == NULL) {
return GetError();
}
const char* extension = extension_name;
if (File::IsAbsolutePath(extension_name)) {
extension = strrchr(extension_name, PathSeparator()) + 1;
}
const char* strings[] = {extension, "_Init", NULL};
const char* init_function_name = Concatenate(strings);
void* init_function = ResolveSymbol(library_handle, init_function_name);
Dart_Handle result = GetError();
if (Dart_IsError(result)) {
return result;
}
ASSERT(init_function != NULL);
typedef Dart_Handle (*InitFunctionType)(Dart_Handle import_map);
InitFunctionType fn = reinterpret_cast<InitFunctionType>(init_function);
return (*fn)(parent_library);
}
// Concatenates a NULL terminated array of strings.
// The returned string is scope allocated.
const char* Extensions::Concatenate(const char** strings) {
int size = 1; // null termination.
for (int i = 0; strings[i] != NULL; i++) {
size += strlen(strings[i]);
}
char* result = reinterpret_cast<char*>(Dart_ScopeAllocate(size));
int index = 0;
for (int i = 0; strings[i] != NULL; i++) {
index += snprintf(result + index, size - index, "%s", strings[i]);
}
ASSERT(index == size - 1);
ASSERT(result[size - 1] == '\0');
return result;
}
} // namespace bin
} // namespace dart

View file

@ -1,47 +0,0 @@
// Copyright (c) 2012, 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.
#ifndef RUNTIME_BIN_EXTENSIONS_H_
#define RUNTIME_BIN_EXTENSIONS_H_
#include "include/dart_api.h"
#include "platform/globals.h"
namespace dart {
namespace bin {
class Extensions {
public:
// TODO(whesse): Make extension load from a relative path relative to
// the library it is in. Currently loads from current working directory.
static Dart_Handle LoadExtension(const char* extension_directory,
const char* extension_name,
Dart_Handle parent_library);
// Platform-specific implementations.
// Don't rename LoadExtensionLibrary to LoadLibrary since on Windows it
// conflicts with LoadLibraryW after mangling.
static void* LoadExtensionLibrary(const char* library_file);
static void* ResolveSymbol(void* lib_handle, const char* symbol);
static void UnloadLibrary(void* lib_handle);
private:
static Dart_Handle GetError();
static void* MakePathAndResolve(const char* dir, const char* name);
static void* ResolveAbsPathExtension(const char* extension_path);
static void* ResolveExtension(const char* extensioion_directory,
const char* extension_name);
// The returned string is scope allocated.
static const char* Concatenate(const char** strings);
DISALLOW_ALLOCATION();
DISALLOW_IMPLICIT_CONSTRUCTORS(Extensions);
};
} // namespace bin
} // namespace dart
#endif // RUNTIME_BIN_EXTENSIONS_H_

View file

@ -1,42 +0,0 @@
// Copyright (c) 2012, 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 "platform/globals.h"
#if defined(DART_HOST_OS_ANDROID)
#include <dlfcn.h> // NOLINT
#include "bin/extensions.h"
#include "platform/assert.h"
namespace dart {
namespace bin {
void* Extensions::LoadExtensionLibrary(const char* library_file) {
return dlopen(library_file, RTLD_LAZY);
}
void* Extensions::ResolveSymbol(void* lib_handle, const char* symbol) {
dlerror();
return dlsym(lib_handle, symbol);
}
void Extensions::UnloadLibrary(void* lib_handle) {
dlerror();
int result = dlclose(lib_handle);
ASSERT(result == 0);
}
Dart_Handle Extensions::GetError() {
const char* err_str = dlerror();
if (err_str != NULL) {
return Dart_NewApiError(err_str);
}
return Dart_Null();
}
} // namespace bin
} // namespace dart
#endif // defined(DART_HOST_OS_ANDROID)

View file

@ -1,46 +0,0 @@
// 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 "platform/globals.h"
#if defined(DART_HOST_OS_FUCHSIA)
#include "bin/extensions.h"
#include <dlfcn.h>
#include <fcntl.h>
#include <lib/fdio/io.h>
#include <zircon/dlfcn.h>
#include "platform/assert.h"
namespace dart {
namespace bin {
void* Extensions::LoadExtensionLibrary(const char* library_file) {
return dlopen(library_file, RTLD_LAZY);
}
void* Extensions::ResolveSymbol(void* lib_handle, const char* symbol) {
dlerror();
return dlsym(lib_handle, symbol);
}
void Extensions::UnloadLibrary(void* lib_handle) {
dlerror();
int result = dlclose(lib_handle);
ASSERT(result == 0);
}
Dart_Handle Extensions::GetError() {
const char* err_str = dlerror();
if (err_str != NULL) {
return Dart_NewApiError(err_str);
}
return Dart_Null();
}
} // namespace bin
} // namespace dart
#endif // defined(DART_HOST_OS_FUCHSIA)

View file

@ -1,42 +0,0 @@
// Copyright (c) 2012, 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 "platform/globals.h"
#if defined(DART_HOST_OS_LINUX)
#include <dlfcn.h> // NOLINT
#include "bin/extensions.h"
#include "platform/assert.h"
namespace dart {
namespace bin {
void* Extensions::LoadExtensionLibrary(const char* library_file) {
return dlopen(library_file, RTLD_LAZY);
}
void* Extensions::ResolveSymbol(void* lib_handle, const char* symbol) {
dlerror();
return dlsym(lib_handle, symbol);
}
void Extensions::UnloadLibrary(void* lib_handle) {
dlerror();
int result = dlclose(lib_handle);
ASSERT(result == 0);
}
Dart_Handle Extensions::GetError() {
const char* err_str = dlerror();
if (err_str != NULL) {
return Dart_NewApiError(err_str);
}
return Dart_Null();
}
} // namespace bin
} // namespace dart
#endif // defined(DART_HOST_OS_LINUX)

View file

@ -1,42 +0,0 @@
// Copyright (c) 2012, 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 "platform/globals.h"
#if defined(DART_HOST_OS_MACOS)
#include <dlfcn.h> // NOLINT
#include "bin/extensions.h"
#include "platform/assert.h"
namespace dart {
namespace bin {
void* Extensions::LoadExtensionLibrary(const char* library_file) {
return dlopen(library_file, RTLD_LAZY);
}
void* Extensions::ResolveSymbol(void* lib_handle, const char* symbol) {
dlerror();
return dlsym(lib_handle, symbol);
}
void Extensions::UnloadLibrary(void* lib_handle) {
dlerror();
int result = dlclose(lib_handle);
ASSERT(result == 0);
}
Dart_Handle Extensions::GetError() {
const char* err_str = dlerror();
if (err_str != NULL) {
return Dart_NewApiError(err_str);
}
return Dart_Null();
}
} // namespace bin
} // namespace dart
#endif // defined(DART_HOST_OS_MACOS)

View file

@ -1,54 +0,0 @@
// Copyright (c) 2012, 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 "platform/globals.h"
#if defined(DART_HOST_OS_WINDOWS)
#include "bin/extensions.h"
#include "bin/utils.h"
#include "bin/utils_win.h"
#include "platform/assert.h"
namespace dart {
namespace bin {
void* Extensions::LoadExtensionLibrary(const char* library_file) {
SetLastError(0);
// Convert to wchar_t string.
int name_len = MultiByteToWideChar(CP_UTF8, 0, library_file, -1, NULL, 0);
wchar_t* name;
name = new wchar_t[name_len];
MultiByteToWideChar(CP_UTF8, 0, library_file, -1, name, name_len);
void* ext = LoadLibraryW(name);
delete[] name;
return ext;
}
void* Extensions::ResolveSymbol(void* lib_handle, const char* symbol) {
SetLastError(0);
return reinterpret_cast<void*>(
GetProcAddress(reinterpret_cast<HMODULE>(lib_handle), symbol));
}
void Extensions::UnloadLibrary(void* lib_handle) {
SetLastError(0);
BOOL result = FreeLibrary(reinterpret_cast<HMODULE>(lib_handle));
ASSERT(result);
}
Dart_Handle Extensions::GetError() {
int last_error = GetLastError();
if (last_error != 0) {
OSError err;
return Dart_NewApiError(err.message());
}
return Dart_Null();
}
} // namespace bin
} // namespace dart
#endif // defined(DART_HOST_OS_WINDOWS)

View file

@ -8,7 +8,6 @@
#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"
@ -49,97 +48,6 @@ Dart_Handle Loader::Init(const char* packages_file,
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) {
auto path = File::UriToPath(lib_uri_str);
lib_path = DartUtils::DirName(path.get());
} else {
lib_path = Utils::StrDup(lib_uri_str);
}
const char* path = DartUtils::RemoveScheme(url_string);
if (!File::IsAbsolutePath(path) && PathContainsSeparator(path)) {
free(lib_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) {
auto path = File::UriToPath(lib_uri);
lib_path = DartUtils::DirName(path.get());
} else {
lib_path = Utils::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)
static void MallocFinalizer(void* isolate_callback_data, void* peer) {
free(peer);
@ -185,13 +93,6 @@ Dart_Handle Loader::LibraryTagHandler(Dart_LibraryTag tag,
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.

View file

@ -20,8 +20,6 @@ class Loader {
static Dart_Handle InitForSnapshot(const char* snapshot_uri,
IsolateData* isolate_data);
static Dart_Handle ReloadNativeExtensions();
// A static tag handler that hides all usage of a loader for an isolate.
static Dart_Handle LibraryTagHandler(Dart_LibraryTag tag,
Dart_Handle library,

View file

@ -16,7 +16,6 @@
#include "bin/dfe.h"
#include "bin/error_exit.h"
#include "bin/eventhandler.h"
#include "bin/extensions.h"
#include "bin/file.h"
#include "bin/gzip.h"
#include "bin/isolate_data.h"
@ -238,11 +237,6 @@ static bool OnIsolateInitialize(void** child_callback_data, char** error) {
}
}
if (isolate_run_app_snapshot) {
result = Loader::ReloadNativeExtensions();
if (Dart_IsError(result)) goto failed;
}
Dart_ExitScope();
return true;
@ -324,11 +318,6 @@ static Dart_Isolate IsolateSetupHelper(Dart_Isolate isolate,
}
#endif // !defined(DART_PRECOMPILED_RUNTIME)
if (isolate_run_app_snapshot) {
Dart_Handle result = Loader::ReloadNativeExtensions();
CHECK_RESULT(result);
}
if (isolate_run_app_snapshot) {
Dart_Handle result = Loader::InitForSnapshot(script_uri, isolate_data);
CHECK_RESULT(result);

View file

@ -10,7 +10,6 @@
#include "bin/dfe.h"
#include "bin/elf_loader.h"
#include "bin/error_exit.h"
#include "bin/extensions.h"
#include "bin/file.h"
#include "bin/platform.h"
#include "include/dart_api.h"
@ -276,7 +275,7 @@ class DylibAppSnapshot : public AppSnapshot {
isolate_snapshot_data_(isolate_snapshot_data),
isolate_snapshot_instructions_(isolate_snapshot_instructions) {}
~DylibAppSnapshot() { Extensions::UnloadLibrary(library_); }
~DylibAppSnapshot() { Utils::UnloadDynamicLibrary(library_); }
void SetBuffers(const uint8_t** vm_data_buffer,
const uint8_t** vm_instructions_buffer,
@ -297,26 +296,29 @@ class DylibAppSnapshot : public AppSnapshot {
};
static AppSnapshot* TryReadAppSnapshotDynamicLibrary(const char* script_name) {
void* library = Extensions::LoadExtensionLibrary(script_name);
if (library == NULL) {
return NULL;
void* library = Utils::LoadDynamicLibrary(script_name);
if (library == nullptr) {
return nullptr;
}
const uint8_t* vm_data_buffer = reinterpret_cast<const uint8_t*>(
Extensions::ResolveSymbol(library, kVmSnapshotDataCSymbol));
Utils::ResolveSymbolInDynamicLibrary(library, kVmSnapshotDataCSymbol));
const uint8_t* vm_instructions_buffer = reinterpret_cast<const uint8_t*>(
Extensions::ResolveSymbol(library, kVmSnapshotInstructionsCSymbol));
const uint8_t* vm_instructions_buffer =
reinterpret_cast<const uint8_t*>(Utils::ResolveSymbolInDynamicLibrary(
library, kVmSnapshotInstructionsCSymbol));
const uint8_t* isolate_data_buffer = reinterpret_cast<const uint8_t*>(
Extensions::ResolveSymbol(library, kIsolateSnapshotDataCSymbol));
if (isolate_data_buffer == NULL) {
const uint8_t* isolate_data_buffer =
reinterpret_cast<const uint8_t*>(Utils::ResolveSymbolInDynamicLibrary(
library, kIsolateSnapshotDataCSymbol));
if (isolate_data_buffer == nullptr) {
FATAL1("Failed to resolve symbol '%s'\n", kIsolateSnapshotDataCSymbol);
}
const uint8_t* isolate_instructions_buffer = reinterpret_cast<const uint8_t*>(
Extensions::ResolveSymbol(library, kIsolateSnapshotInstructionsCSymbol));
if (isolate_instructions_buffer == NULL) {
const uint8_t* isolate_instructions_buffer =
reinterpret_cast<const uint8_t*>(Utils::ResolveSymbolInDynamicLibrary(
library, kIsolateSnapshotInstructionsCSymbol));
if (isolate_instructions_buffer == nullptr) {
FATAL1("Failed to resolve symbol '%s'\n",
kIsolateSnapshotInstructionsCSymbol);
}

View file

@ -1,73 +0,0 @@
/* Copyright (c) 2012, 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 <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "include/dart_api.h"
#if defined(ASSERT)
#error ASSERT already defined!
#endif
/* Native methods. */
void IfNull(Dart_NativeArguments arguments) {
Dart_Handle object = Dart_GetNativeArgument(arguments, 0);
if (Dart_IsNull(object)) {
Dart_SetReturnValue(arguments, Dart_GetNativeArgument(arguments, 1));
} else {
Dart_SetReturnValue(arguments, object);
}
}
void ThrowMeTheBall(Dart_NativeArguments arguments) {
Dart_Handle object = Dart_GetNativeArgument(arguments, 0);
Dart_ThrowException(object);
}
/* Native resolver for the extension library. */
Dart_NativeFunction ResolveName(Dart_Handle name,
int argc,
bool* auto_setup_scope) {
/* assert(Dart_IsString(name)); */
const char* c_name;
Dart_Handle check_error;
if (auto_setup_scope == NULL) {
return NULL;
}
*auto_setup_scope = 1;
check_error = Dart_StringToCString(name, &c_name);
if (Dart_IsError(check_error)) {
Dart_PropagateError(check_error);
}
if ((strcmp("TestExtension_IfNull", c_name) == 0) && (argc == 2)) {
return IfNull;
}
if ((strcmp("TestExtension_ThrowMeTheBall", c_name) == 0) && (argc == 1)) {
return ThrowMeTheBall;
}
return NULL;
}
/* Native entry point for the extension library. */
DART_EXPORT Dart_Handle test_extension_Init(Dart_Handle parent_library) {
Dart_Handle result_code;
if (Dart_IsError(parent_library)) {
return parent_library;
}
result_code = Dart_SetNativeResolver(parent_library, ResolveName, NULL);
if (Dart_IsError(result_code)) {
return result_code;
}
return parent_library;
}

View file

@ -1,15 +0,0 @@
// Copyright (c) 2012, 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 "platform/globals.h"
#if defined(DART_HOST_OS_WINDOWS)
#define WIN32_LEAN_AND_MEAN
#include <windows.h> // NOLINT
BOOL APIENTRY DllMain(HMODULE module, DWORD reason, LPVOID reserved) {
return true;
}
#endif // defined(DART_HOST_OS_WINDOWS)

View file

@ -3136,7 +3136,6 @@ typedef enum {
Dart_kCanonicalizeUrl = 0,
Dart_kImportTag,
Dart_kKernelTag,
Dart_kImportExtensionTag,
} Dart_LibraryTag;
/**
@ -3171,10 +3170,6 @@ typedef enum {
* script tags. The return value should be an error or a TypedData containing
* the kernel bytes.
*
* Dart_kImportExtensionTag
*
* This tag is used to load an external import (shared object file). The
* extension path must have the scheme 'dart-ext:'.
*/
typedef Dart_Handle (*Dart_LibraryTagHandler)(
Dart_LibraryTag tag,

View file

@ -8,71 +8,52 @@
#include "vm/globals.h"
#include "vm/native_entry.h"
#if !defined(DART_HOST_OS_LINUX) && !defined(DART_HOST_OS_MACOS) && \
!defined(DART_HOST_OS_ANDROID) && !defined(DART_HOST_OS_FUCHSIA)
// TODO(dacoharkes): Implement dynamic libraries for other targets & merge the
// implementation with:
// - runtime/bin/extensions.h
// - runtime/bin/extensions_linux.cc
// TODO(dacoharkes): Make the code from bin available in a manner similar to
// runtime/vm/dart.h Dart_FileReadCallback.
#else
#if defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_MACOS) || \
defined(DART_HOST_OS_ANDROID) || defined(DART_HOST_OS_FUCHSIA)
#include <dlfcn.h>
#endif
namespace dart {
static void* LoadExtensionLibrary(const char* library_file) {
#if defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_MACOS) || \
defined(DART_HOST_OS_ANDROID) || defined(DART_HOST_OS_FUCHSIA)
void* handle = dlopen(library_file, RTLD_LAZY);
if (handle == nullptr) {
char* error = dlerror();
static void* LoadDynamicLibrary(const char* library_file) {
char* error = nullptr;
void* handle = Utils::LoadDynamicLibrary(library_file, &error);
if (error != nullptr) {
const String& msg = String::Handle(String::NewFormatted(
"Failed to load dynamic library '%s': %s", library_file, error));
"Failed to load dynamic library '%s': %s",
library_file != nullptr ? library_file : "<process>", error));
free(error);
Exceptions::ThrowArgumentError(msg);
}
return handle;
#elif defined(DART_HOST_OS_WINDOWS)
SetLastError(0); // Clear any errors.
}
void* ext;
if (library_file == nullptr) {
ext = GetModuleHandle(nullptr);
} else {
// Convert to wchar_t string.
const int name_len =
MultiByteToWideChar(CP_UTF8, 0, library_file, -1, NULL, 0);
wchar_t* name = new wchar_t[name_len];
MultiByteToWideChar(CP_UTF8, 0, library_file, -1, name, name_len);
ext = LoadLibraryW(name);
delete[] name;
}
if (ext == nullptr) {
const int error = GetLastError();
static void* ResolveSymbol(void* handle, const char* symbol) {
char* error = nullptr;
void* result = Utils::ResolveSymbolInDynamicLibrary(handle, symbol, &error);
if (error != nullptr) {
const String& msg = String::Handle(String::NewFormatted(
"Failed to load dynamic library '%s': %i", library_file, error));
"Failed to lookup symbol '%s': %s", symbol, error));
free(error);
Exceptions::ThrowArgumentError(msg);
}
return result;
}
return ext;
#else
const Array& args = Array::Handle(Array::New(1));
args.SetAt(0,
String::Handle(String::New(
"The dart:ffi library is not available on this platform.")));
Exceptions::ThrowByType(Exceptions::kUnsupported, args);
#endif
static bool SymbolExists(void* handle, const char* symbol) {
char* error = nullptr;
Utils::ResolveSymbolInDynamicLibrary(handle, symbol, &error);
if (error != nullptr) {
free(error);
return false;
}
return true;
}
DEFINE_NATIVE_ENTRY(Ffi_dl_open, 0, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(String, lib_path, arguments->NativeArgAt(0));
void* handle = LoadExtensionLibrary(lib_path.ToCString());
void* handle = LoadDynamicLibrary(lib_path.ToCString());
return DynamicLibrary::New(handle);
}
@ -91,39 +72,7 @@ DEFINE_NATIVE_ENTRY(Ffi_dl_processLibrary, 0, 0) {
}
DEFINE_NATIVE_ENTRY(Ffi_dl_executableLibrary, 0, 0) {
return DynamicLibrary::New(LoadExtensionLibrary(nullptr));
}
static void* ResolveSymbol(void* handle, const char* symbol) {
#if defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_MACOS) || \
defined(DART_HOST_OS_ANDROID) || defined(DART_HOST_OS_FUCHSIA)
dlerror(); // Clear any errors.
void* pointer = dlsym(handle, symbol);
char* error = dlerror();
if (error != nullptr) {
const String& msg = String::Handle(
String::NewFormatted("Failed to lookup symbol (%s)", error));
Exceptions::ThrowArgumentError(msg);
}
return pointer;
#elif defined(DART_HOST_OS_WINDOWS)
SetLastError(0);
void* pointer = reinterpret_cast<void*>(
GetProcAddress(reinterpret_cast<HMODULE>(handle), symbol));
if (pointer == nullptr) {
const int error = GetLastError();
const String& msg = String::Handle(
String::NewFormatted("Failed to lookup symbol (%i)", error));
Exceptions::ThrowArgumentError(msg);
}
return pointer;
#else
const Array& args = Array::Handle(Array::New(1));
args.SetAt(0,
String::Handle(String::New(
"The dart:ffi library is not available on this platform.")));
Exceptions::ThrowByType(Exceptions::kUnsupported, args);
#endif
return DynamicLibrary::New(LoadDynamicLibrary(nullptr));
}
DEFINE_NATIVE_ENTRY(Ffi_dl_lookup, 1, 2) {
@ -147,25 +96,6 @@ DEFINE_NATIVE_ENTRY(Ffi_dl_getHandle, 0, 1) {
return Integer::NewFromUint64(handle);
}
static bool SymbolExists(void* handle, const char* symbol) {
#if defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_MACOS) || \
defined(DART_HOST_OS_ANDROID) || defined(DART_HOST_OS_FUCHSIA)
dlerror(); // Clear previous error, if any.
dlsym(handle, symbol);
// Checking whether dlsym returns a nullptr is not enough, as the value of
// the symbol could actually be NULL. Check the error condition instead.
return dlerror() == nullptr;
#elif defined(DART_HOST_OS_WINDOWS)
return GetProcAddress(reinterpret_cast<HMODULE>(handle), symbol) != nullptr;
#else
const Array& args = Array::Handle(Array::New(1));
args.SetAt(0,
String::Handle(String::New(
"The dart:ffi library is not available on this platform.")));
Exceptions::ThrowByType(Exceptions::kUnsupported, args);
#endif
}
DEFINE_NATIVE_ENTRY(Ffi_dl_providesSymbol, 0, 2) {
GET_NON_NULL_NATIVE_ARGUMENT(DynamicLibrary, dlib, arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(String, argSymbolName,

View file

@ -7,6 +7,11 @@
#include "platform/allocation.h"
#include "platform/globals.h"
#if defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_MACOS) || \
defined(DART_HOST_OS_ANDROID) || defined(DART_HOST_OS_FUCHSIA)
#include <dlfcn.h>
#endif
namespace dart {
// Implementation is from "Hacker's Delight" by Henry S. Warren, Jr.,
@ -347,4 +352,95 @@ Utils::CStringUniquePtr Utils::CreateCStringUniquePtr(char* str) {
return std::unique_ptr<char, decltype(std::free)*>{str, std::free};
}
static void GetLastErrorAsString(char** error) {
if (error == nullptr) return; // Nothing to do.
#if defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_MACOS) || \
defined(DART_HOST_OS_ANDROID) || defined(DART_HOST_OS_FUCHSIA)
const char* status = dlerror();
*error = status != nullptr ? strdup(status) : nullptr;
#elif defined(DART_HOST_OS_WINDOWS)
const int status = GetLastError();
*error = status != 0 ? Utils::SCreate("error code %i", error) : nullptr;
#else
*error = Utils::StrDup("loading dynamic libraries is not supported");
#endif
}
void* Utils::LoadDynamicLibrary(const char* library_path, char** error) {
void* handle = nullptr;
#if defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_MACOS) || \
defined(DART_HOST_OS_ANDROID) || defined(DART_HOST_OS_FUCHSIA)
handle = dlopen(library_path, RTLD_LAZY);
#elif defined(DART_HOST_OS_WINDOWS)
SetLastError(0); // Clear any errors.
if (library_path == nullptr) {
handle = GetModuleHandle(nullptr);
} else {
// Convert to wchar_t string.
const int name_len = MultiByteToWideChar(
CP_UTF8, /*dwFlags=*/0, library_path, /*cbMultiByte=*/-1, nullptr, 0);
if (name_len != 0) {
std::unique_ptr<wchar_t[]> name(new wchar_t[name_len]);
const int written_len =
MultiByteToWideChar(CP_UTF8, /*dwFlags=*/0, library_path,
/*cbMultiByte=*/-1, name.get(), name_len);
RELEASE_ASSERT(written_len == name_len);
handle = LoadLibraryW(name.get());
}
}
#endif
if (handle == nullptr) {
GetLastErrorAsString(error);
}
return handle;
}
void* Utils::ResolveSymbolInDynamicLibrary(void* library_handle,
const char* symbol,
char** error) {
void* result = nullptr;
#if defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_MACOS) || \
defined(DART_HOST_OS_ANDROID) || defined(DART_HOST_OS_FUCHSIA)
dlerror(); // Clear any errors.
result = dlsym(library_handle, symbol);
// Note: nullptr might be a valid return from dlsym. Must call dlerror
// to differentiate.
GetLastErrorAsString(error);
return result;
#elif defined(DART_HOST_OS_WINDOWS)
SetLastError(0);
result = reinterpret_cast<void*>(
GetProcAddress(reinterpret_cast<HMODULE>(library_handle), symbol));
#endif
if (result == nullptr) {
GetLastErrorAsString(error);
}
return result;
}
void Utils::UnloadDynamicLibrary(void* library_handle, char** error) {
bool ok = false;
#if defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_MACOS) || \
defined(DART_HOST_OS_ANDROID) || defined(DART_HOST_OS_FUCHSIA)
ok = dlclose(library_handle) == 0;
#elif defined(DART_HOST_OS_WINDOWS)
SetLastError(0); // Clear any errors.
ok = FreeLibrary(reinterpret_cast<HMODULE>(library_handle));
#endif
if (!ok) {
GetLastErrorAsString(error);
}
}
} // namespace dart

View file

@ -479,6 +479,33 @@ class Utils {
// Returns str in a unique_ptr with free used as its deleter.
static CStringUniquePtr CreateCStringUniquePtr(char* str);
// Load dynamic library from the given |library_path| and return the
// library handle. |library_path| can be |nullptr| in which case
// library handle representing the executable is returned.
// If an error occurs returns |nullptr| and populates
// |error| (if provided) with an error message (caller must free this message
// when it is no longer needed).
static void* LoadDynamicLibrary(const char* library_path,
char** error = nullptr);
// Resolve the given |symbol| within the library referenced by the
// given |library_handle|.
// If an error occurs populates |error| (if provided) with an error message
// (caller must free this message when it is no longer needed).
// Note: on some platforms |nullptr| is a valid value for a symbol, so to
// check if resolution succeeded one must instead provide non-null |error|
// and then check if it was populated with an error message.
static void* ResolveSymbolInDynamicLibrary(void* library_handle,
const char* symbol,
char** error = nullptr);
// Unload the library referenced by the given |library_handle|.
// If an error occurs returns |nullptr| and populates
// |error| (if provided) with an error message (caller must free this message
// when it is no longer needed).
static void UnloadDynamicLibrary(void* library_handle,
char** error = nullptr);
};
} // namespace dart

View file

@ -3,18 +3,16 @@
// BSD-style license that can be found in the LICENSE file.
//
// VMOptions=--verify-entry-points=true
// SharedObjects=entrypoints_verification_test
import 'dart:io';
import 'dart:convert';
import 'dart:math';
import 'package:path/path.dart';
import 'package:expect/expect.dart';
import 'dart-ext:entrypoints_verification_test_extension';
void RunTest() native "RunTest";
import 'dart:ffi';
import './dylib_utils.dart';
main() {
RunTest();
final helper = dlopenPlatformSpecific('entrypoints_verification_test');
final runTest =
helper.lookupFunction<Void Function(), void Function()>('RunTests');
runTest();
new C();
new D();

View file

@ -3,20 +3,18 @@
// BSD-style license that can be found in the LICENSE file.
//
// VMOptions=--verify-entry-points=true
// SharedObjects=entrypoints_verification_test
// @dart = 2.9
import 'dart:io';
import 'dart:convert';
import 'dart:math';
import 'package:path/path.dart';
import 'package:expect/expect.dart';
import 'dart-ext:entrypoints_verification_test_extension';
void RunTest() native "RunTest";
import 'dart:ffi';
import './dylib_utils.dart';
main() {
RunTest();
final helper = dlopenPlatformSpecific('entrypoints_verification_test');
final runTest =
helper.lookupFunction<Void Function(), void Function()>('RunTests');
runTest();
new C();
new D();

View file

@ -369,6 +369,10 @@ dart_2/thread_priority_windows_test: SkipByDesign
dart/thread_priority_linux_test: SkipByDesign
dart_2/thread_priority_linux_test: SkipByDesign
[ $arch != x64 || $system != linux || $hot_reload || $compiler != dartk && $compiler != dartkp ]
dart/entrypoints_verification_test: SkipByDesign # Enough to test on x64 Linux.
dart_2/entrypoints_verification_test: SkipByDesign # Enough to test on x64 Linux.
[ $builder_tag == crossword || $builder_tag == crossword_ast ]
dart/emit_aot_size_info_flag_test: SkipByDesign # The test itself cannot determine the location of gen_snapshot (only tools/test.py knows where it is).
dart/gen_snapshot_include_resolved_urls_test: SkipByDesign # The test doesn't know location of cross-platform gen_snapshot.

View file

@ -722,18 +722,9 @@ bool IsolateGroupReloadContext::Reload(bool force_reload,
//
// If loading the hot-reload diff succeeded we'll finalize the loading, which
// will either commit or reject the reload request.
auto& result = Object::Handle(Z);
{
// We need to set an active isolate while loading kernel. The kernel loader
// itself is independent of the current isolate, but if the application
// needs native extensions, the kernel loader calls out to the embedder to
// load those, which requires currently an active isolate (since embedder
// will callback into VM using Dart API).
DisabledNoActiveIsolateScope active_isolate_scope(&no_active_isolate_scope);
result = IG->program_reload_context()->ReloadPhase2LoadKernel(
kernel_program.get(), root_lib_url_);
}
const auto& result =
Object::Handle(Z, IG->program_reload_context()->ReloadPhase2LoadKernel(
kernel_program.get(), root_lib_url_));
if (result.IsError()) {
TIR_Print("---- LOAD FAILED, ABORTING RELOAD\n");
@ -937,9 +928,7 @@ void IsolateGroupReloadContext::BuildModifiedLibrariesClosure(
if (!ns.IsNull()) {
target = ns.target();
target_url = target.url();
if (!target_url.StartsWith(Symbols::DartExtensionScheme())) {
(*imported_by)[target.index()]->Add(lib.index());
}
(*imported_by)[target.index()]->Add(lib.index());
}
}

View file

@ -590,89 +590,6 @@ bool KernelLoader::IsClassName(NameIndex name,
return H.StringEquals(library_name_index, library.ToCString());
}
void KernelLoader::LoadNativeExtensionLibraries() {
const auto& potential_extension_libraries =
GrowableObjectArray::Handle(Z, H.GetPotentialExtensionLibraries());
if (potential_extension_libraries.IsNull()) {
return;
}
// Prepare lazy constant reading.
ConstantReader constant_reader(&helper_, &active_class_);
// Obtain `dart:_internal::ExternalName.name`.
EnsureExternalClassIsLookedUp();
Instance& constant = Instance::Handle(Z);
String& uri_path = String::Handle(Z);
Library& library = Library::Handle(Z);
const intptr_t length = potential_extension_libraries.Length();
for (intptr_t i = 0; i < length; ++i) {
library ^= potential_extension_libraries.At(i);
helper_.SetOffset(library.kernel_offset());
LibraryHelper library_helper(&helper_, kernel_binary_version_);
library_helper.ReadUntilExcluding(LibraryHelper::kAnnotations);
const intptr_t annotation_count = helper_.ReadListLength();
for (intptr_t j = 0; j < annotation_count; ++j) {
uri_path = String::null();
const intptr_t tag = helper_.PeekTag();
if (tag == kConstantExpression) {
helper_.ReadByte(); // Skip the tag.
helper_.ReadPosition(); // Skip fileOffset.
helper_.SkipDartType(); // Skip type.
// We have a candidate. Let's look if it's an instance of the
// ExternalName class.
const intptr_t constant_table_index = helper_.ReadUInt();
if (constant_reader.IsInstanceConstant(constant_table_index,
external_name_class_)) {
constant = constant_reader.ReadConstant(constant_table_index);
ASSERT(constant.clazz() == external_name_class_.ptr());
uri_path ^= constant.GetField(external_name_field_);
}
} else {
helper_.SkipExpression();
}
if (uri_path.IsNull()) continue;
LoadNativeExtension(library, uri_path);
// Create a dummy library and add it as an import to the current
// library. This allows later to discover and reload this native
// extension, e.g. when running from an app-jit snapshot.
// See Loader::ReloadNativeExtensions(...) which relies on
// Dart_GetImportsOfScheme('dart-ext').
const auto& native_library = Library::Handle(Library::New(uri_path));
library.AddImport(Namespace::Handle(Namespace::New(
native_library, Array::null_array(), Array::null_array(), library)));
}
}
}
void KernelLoader::LoadNativeExtension(const Library& library,
const String& uri_path) {
#if !defined(DART_PRECOMPILER)
if (!IG->HasTagHandler()) {
H.ReportError("no library handler registered.");
}
I->BlockClassFinalization();
const auto& result = Object::Handle(
Z, IG->CallTagHandler(Dart_kImportExtensionTag, library, uri_path));
I->UnblockClassFinalization();
if (result.IsError()) {
H.ReportError(Error::Cast(result), "library handler failed");
}
#endif
}
ObjectPtr KernelLoader::LoadProgram(bool process_pending_classes) {
SafepointWriteRwLocker ml(thread_, thread_->isolate_group()->program_lock());
ASSERT(kernel_program_info_.constants() == Array::null());
@ -712,7 +629,6 @@ ObjectPtr KernelLoader::LoadProgram(bool process_pending_classes) {
kernel_program_info_.set_constants(array);
H.SetConstants(array); // for caching
AnnotateNativeProcedures();
LoadNativeExtensionLibraries();
EvaluateDelayedPragmas();
NameIndex main = program_->main_method();

View file

@ -227,8 +227,6 @@ class KernelLoader : public ValueObject {
bool IsClassName(NameIndex name, const String& library, const String& klass);
void AnnotateNativeProcedures();
void LoadNativeExtensionLibraries();
void LoadNativeExtension(const Library& library, const String& uri_path);
void EvaluateDelayedPragmas();
void ReadVMAnnotations(const Library& library,

View file

@ -18,7 +18,7 @@ class NativeArguments;
// - bootstrap natives, which are called directly from stub code. The callee is
// responsible for safepoint transitions and setting up handle scopes as
// needed. Only VM-defined natives are bootstrap natives; they cannot be
// defined by embedders or native extensions.
// defined by embedders.
// - no scope natives, which are called through a wrapper function. The wrapper
// function handles the safepoint transition. The callee is responsible for
// setting up API scopes as needed.

View file

@ -13148,35 +13148,7 @@ NamespacePtr Library::ImportAt(intptr_t index) const {
}
void Library::DropDependenciesAndCaches() const {
// We need to preserve the "dart-ext:" imports because they are used by
// Loader::ReloadNativeExtensions().
intptr_t native_import_count = 0;
Array& imports = Array::Handle(untag()->imports());
Namespace& ns = Namespace::Handle();
Library& lib = Library::Handle();
String& url = String::Handle();
for (int i = 0; i < imports.Length(); ++i) {
ns = Namespace::RawCast(imports.At(i));
if (ns.IsNull()) continue;
lib = ns.target();
url = lib.url();
if (url.StartsWith(Symbols::DartExtensionScheme())) {
native_import_count++;
}
}
Array& new_imports =
Array::Handle(Array::New(native_import_count, Heap::kOld));
for (int i = 0, j = 0; i < imports.Length(); ++i) {
ns = Namespace::RawCast(imports.At(i));
if (ns.IsNull()) continue;
lib = ns.target();
url = lib.url();
if (url.StartsWith(Symbols::DartExtensionScheme())) {
new_imports.SetAt(j++, ns);
}
}
untag()->set_imports(new_imports.ptr());
untag()->set_imports(Object::empty_array().ptr());
untag()->set_exports(Object::empty_array().ptr());
StoreNonPointer(&untag()->num_imports_, 0);
untag()->set_resolved_names(Array::null());

View file

@ -429,7 +429,7 @@ mode and will no longer accept incoming web socket connections, instead forwardi
the web socket connection request to DDS. If DDS disconnects from the VM service,
the VM service will once again start accepting incoming web socket connections.
The VM service forwards the web socket connection by issuing a redirect
The VM service forwards the web socket connection by issuing a redirect
### Protocol Extensions
@ -3298,9 +3298,8 @@ class MemoryUsage extends Response {
// example, memory associated with Dart objects through APIs such as
// Dart_NewFinalizableHandle, Dart_NewWeakPersistentHandle and
// Dart_NewExternalTypedData. This usage is only as accurate as the values
// supplied to these APIs from the VM embedder or native extensions. This
// external memory applies GC pressure, but is separate from heapUsage and
// heapCapacity.
// supplied to these APIs from the VM embedder. This external memory applies
// GC pressure, but is separate from heapUsage and heapCapacity.
int externalUsage;
// The total capacity of the heap in bytes. This is the amount of memory used

View file

@ -61,7 +61,6 @@ class ObjectPointerVisitor;
V(DartCore, "dart:core") \
V(DartDeveloper, "dart:developer") \
V(DartDeveloperTimeline, "dart.developer.timeline") \
V(DartExtensionScheme, "dart-ext:") \
V(DartFfi, "dart:ffi") \
V(DartInternal, "dart:_internal") \
V(DartIsVM, "dart.isVM") \

View file

@ -1,9 +0,0 @@
/Makefile
/*.Makefile
/*.sln
/*.target.mk
/*.vcproj
/*.vcxproj
/*.vcxproj.filters
/*.vcxproj.user
/*.xcodeproj

View file

@ -1,13 +0,0 @@
This directory contains samples of native extensions.
To run the samples, first build both the Dart SDK and the runtime. For example:
```
$ ./tools/build.py create_sdk runtime
```
Then execute the sample programs. For example:
```
$ xcodebuild/ReleaseX64/dart samples/sample_extension/test/sample_extension_test.dart
```

View file

@ -1,39 +0,0 @@
// Copyright (c) 2012, 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.
library sample_asynchronous_extension;
import 'dart:async';
import 'dart:isolate';
import 'dart-ext:sample_extension';
// A class caches the native port used to call an asynchronous extension.
class RandomArray {
static SendPort? _port;
Future<List<int>> randomArray(int seed, int length) {
var completer = new Completer<List<int>>();
var replyPort = new RawReceivePort();
var args = [seed, length, replyPort.sendPort];
_servicePort.send(args);
replyPort.handler = (result) {
replyPort.close();
if (result != null) {
completer.complete(result);
} else {
completer.completeError(new Exception("Random array creation failed"));
}
};
return completer.future;
}
SendPort get _servicePort {
if (_port == null) {
_port = _newServicePort();
}
return _port!;
}
SendPort _newServicePort() native "RandomArray_ServicePort";
}

View file

@ -1,191 +0,0 @@
// Copyright (c) 2012, 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 <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "include/dart_api.h"
#include "include/dart_native_api.h"
Dart_NativeFunction ResolveName(Dart_Handle name,
int argc,
bool* auto_setup_scope);
DART_EXPORT Dart_Handle sample_extension_Init(Dart_Handle parent_library) {
if (Dart_IsError(parent_library)) {
return parent_library;
}
Dart_Handle result_code =
Dart_SetNativeResolver(parent_library, ResolveName, NULL);
if (Dart_IsError(result_code)) {
return result_code;
}
return Dart_Null();
}
Dart_Handle HandleError(Dart_Handle handle) {
if (Dart_IsError(handle)) {
Dart_PropagateError(handle);
}
return handle;
}
void SystemRand(Dart_NativeArguments arguments) {
Dart_EnterScope();
Dart_Handle result = HandleError(Dart_NewInteger(rand()));
Dart_SetReturnValue(arguments, result);
Dart_ExitScope();
}
void SystemSrand(Dart_NativeArguments arguments) {
Dart_EnterScope();
bool success = false;
Dart_Handle seed_object = HandleError(Dart_GetNativeArgument(arguments, 0));
if (Dart_IsInteger(seed_object)) {
bool fits;
HandleError(Dart_IntegerFitsIntoInt64(seed_object, &fits));
if (fits) {
int64_t seed;
HandleError(Dart_IntegerToInt64(seed_object, &seed));
srand(static_cast<unsigned>(seed));
success = true;
}
}
Dart_SetReturnValue(arguments, HandleError(Dart_NewBoolean(success)));
Dart_ExitScope();
}
uint8_t* randomArray(int seed, int length) {
if (length <= 0 || length > 10000000) {
return NULL;
}
uint8_t* values = reinterpret_cast<uint8_t*>(malloc(length));
if (NULL == values) {
return NULL;
}
srand(seed);
for (int i = 0; i < length; ++i) {
values[i] = rand() % 256;
}
return values;
}
void wrappedRandomArray(Dart_Port dest_port_id,
Dart_CObject* message) {
Dart_Port reply_port_id = ILLEGAL_PORT;
if (message->type == Dart_CObject_kArray &&
3 == message->value.as_array.length) {
// Use .as_array and .as_int32 to access the data in the Dart_CObject.
Dart_CObject* param0 = message->value.as_array.values[0];
Dart_CObject* param1 = message->value.as_array.values[1];
Dart_CObject* param2 = message->value.as_array.values[2];
if (param0->type == Dart_CObject_kInt32 &&
param1->type == Dart_CObject_kInt32 &&
param2->type == Dart_CObject_kSendPort) {
int seed = param0->value.as_int32;
int length = param1->value.as_int32;
reply_port_id = param2->value.as_send_port.id;
uint8_t* values = randomArray(seed, length);
if (values != NULL) {
Dart_CObject result;
result.type = Dart_CObject_kTypedData;
result.value.as_typed_data.type = Dart_TypedData_kUint8;
result.value.as_typed_data.values = values;
result.value.as_typed_data.length = length;
if (Dart_PostCObject(reply_port_id, &result)) {
Dart_CObject error;
error.type = Dart_CObject_kNull;
Dart_PostCObject(reply_port_id, &error);
}
free(values);
// It is OK that result is destroyed when function exits.
// Dart_PostCObject has copied its data.
return;
}
}
}
fprintf(stderr, "Invalid message received, cannot proceed. Aborting the process.\n");
abort();
}
void randomArrayServicePort(Dart_NativeArguments arguments) {
Dart_EnterScope();
Dart_SetReturnValue(arguments, Dart_Null());
Dart_Port service_port =
Dart_NewNativePort("RandomArrayService", wrappedRandomArray, true);
if (service_port != ILLEGAL_PORT) {
Dart_Handle send_port = HandleError(Dart_NewSendPort(service_port));
Dart_SetReturnValue(arguments, send_port);
}
Dart_ExitScope();
}
struct FunctionLookup {
const char* name;
Dart_NativeFunction function;
};
FunctionLookup function_list[] = {
{"SystemRand", SystemRand},
{"SystemSrand", SystemSrand},
{"RandomArray_ServicePort", randomArrayServicePort},
{NULL, NULL}};
FunctionLookup no_scope_function_list[] = {
{"NoScopeSystemRand", SystemRand},
{NULL, NULL}
};
Dart_NativeFunction ResolveName(Dart_Handle name,
int argc,
bool* auto_setup_scope) {
if (!Dart_IsString(name)) {
return NULL;
}
Dart_NativeFunction result = NULL;
if (auto_setup_scope == NULL) {
return NULL;
}
Dart_EnterScope();
const char* cname;
HandleError(Dart_StringToCString(name, &cname));
for (int i=0; function_list[i].name != NULL; ++i) {
if (strcmp(function_list[i].name, cname) == 0) {
*auto_setup_scope = true;
result = function_list[i].function;
break;
}
}
if (result != NULL) {
Dart_ExitScope();
return result;
}
for (int i=0; no_scope_function_list[i].name != NULL; ++i) {
if (strcmp(no_scope_function_list[i].name, cname) == 0) {
*auto_setup_scope = false;
result = no_scope_function_list[i].function;
break;
}
}
Dart_ExitScope();
return result;
}

View file

@ -1,16 +0,0 @@
// Copyright (c) 2012, 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.
#if defined(_WIN32)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
BOOL APIENTRY DllMain(HMODULE module,
DWORD reason,
LPVOID reserved) {
return true;
}
#endif // defined(_WIN32)

View file

@ -1,12 +0,0 @@
// Copyright (c) 2012, 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.
library sample_synchronous_extension;
import 'dart-ext:sample_extension';
// The simplest way to call native code: top-level functions.
int systemRand() native "SystemRand";
int noScopeSystemRand() native "NoScopeSystemRand";
bool systemSrand(int seed) native "SystemSrand";

View file

@ -1,16 +0,0 @@
// 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.
//
// Dart test program for testing native extensions.
// OtherResources=../sample_synchronous_extension.dart
// OtherResources=../sample_asynchronous_extension.dart
// OtherResources=../test_sample_synchronous_extension.dart
// OtherResources=../test_sample_asynchronous_extension.dart
import 'sample_extension_test_helper.dart';
void main() {
testNativeExtensions("app-jit");
}

View file

@ -1,11 +0,0 @@
// 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.
//
// Dart test program for testing native extensions.
import 'sample_extension_test_helper.dart';
void main() {
testNativeExtensions(null /* no snapshot */);
}

View file

@ -1,114 +0,0 @@
// Copyright (c) 2013, 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.
//
// Dart test program for testing native extensions.
import 'dart:async';
import 'dart:io';
import 'dart:isolate';
import "package:expect/expect.dart";
import "package:path/path.dart";
Future copyFileToDirectory(String file, String directory) async {
String src = file;
String dst = directory;
ProcessResult result;
switch (Platform.operatingSystem) {
case 'linux':
case 'macos':
result = await Process.run('cp', [src, dst]);
break;
case 'windows':
result = await Process.run('cmd.exe', ['/C', 'copy $src $dst']);
break;
default:
throw 'Unknown operating system ${Platform.operatingSystem}';
}
if (result.exitCode != 0) {
print(result.stdout);
print(result.stderr);
throw "Failed to copy test file ($file) to temporary directory ($directory)";
}
}
Future run(String program, List<String> arguments) async {
print("+ $program ${arguments.join(' ')}");
ProcessResult result = await Process.run(program, arguments);
if (result.exitCode != 0) {
print('Failing process stdout: ${result.stdout}');
print('Failing process stderr: ${result.stderr}');
print('End failing process stderr');
Expect.fail('Test failed with exit code ${result.exitCode}');
}
}
Future runTests(
String program, String testDirectory, String? snapshotKind) async {
for (var test in [
'test_sample_synchronous_extension.dart',
'test_sample_asynchronous_extension.dart'
]) {
String script = join(testDirectory, test);
String snapshot;
if (snapshotKind == null) {
snapshot = script;
} else {
snapshot = join(testDirectory, "$test.snapshot");
await run(Platform.executable, <String>[
...Platform.executableArguments,
'--snapshot=$snapshot',
'--snapshot-kind=$snapshotKind',
script
]);
}
await run(program, <String>[...Platform.executableArguments, snapshot]);
}
}
Future testNativeExtensions(String? snapshotKind) async {
String buildDirectory = dirname(Platform.executable);
Directory tempDirectory =
Directory.systemTemp.createTempSync('sample_extension_');
try {
String testDirectory = tempDirectory.path;
String sourceDirectory = Platform.script.resolve('..').toFilePath();
// Copy sample_extension dart files and sample_extension tests to the
// temporary test directory.
for (var file in [
'sample_synchronous_extension.dart',
'sample_asynchronous_extension.dart',
'test_sample_synchronous_extension.dart',
'test_sample_asynchronous_extension.dart'
]) {
await copyFileToDirectory(join(sourceDirectory, file), testDirectory);
}
// Test native library resolution when it's next to the binary
await runTests(Platform.executable, testDirectory, snapshotKind);
// Test native library resolution when it's next to the source
await copyFileToDirectory(
join(
buildDirectory,
(Platform.isWindows ? '' : 'lib') +
'sample_extension' +
(Platform.isWindows
? '.dll'
: Platform.isMacOS
? '.dylib'
: '.so')),
testDirectory);
Directory tempBinDirectory = Directory(join(tempDirectory.path, 'dart-bin'))
..createSync();
await copyFileToDirectory(Platform.executable, tempBinDirectory.path);
String copyPlatformExecutable =
join(tempBinDirectory.path, basename(Platform.executable));
await runTests(copyPlatformExecutable, testDirectory, snapshotKind);
} finally {
tempDirectory.deleteSync(recursive: true);
}
}

View file

@ -1,58 +0,0 @@
// Copyright (c) 2012, 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.
library test_sample_extension;
import 'sample_asynchronous_extension.dart';
void check(bool condition, String message) {
if (!condition) {
throw new StateError(message);
}
}
void main() {
RandomArray r = new RandomArray();
r.randomArray(17, 100).then((list_100) {
r.randomArray(17, 200).then((list_200) {
for (var i = 0; i < 100; ++i) {
check(list_100[i] == list_200[i], "list_100[i] == list_200[i]");
}
});
});
// Gets a list of 256000 random uint8 values, using seed 19, and
// runs checkNormal on that list.
r.randomArray(19, 256000).then(checkNormal);
}
void checkNormal(List l) {
// Count how many times each byte value occurs. Assert that the counts
// are all within a reasonable (six-sigma) range.
List<int> counts = new List<int>.filled(256, 0);
for (var e in l) {
counts[e]++;
}
new RandomArray().randomArray(18, 256000).then(checkCorrelation(counts));
}
dynamic Function(List<int>) checkCorrelation(List<int> counts) {
return (List<int> l) {
List<int> counts_2 = new List<int>.filled(256, 0);
for (var e in l) {
counts_2[e]++;
}
var product = 0;
for (var i = 0; i < 256; ++i) {
check(counts[i] < 1200, "counts[i] < 1200");
check(counts_2[i] < 1200, "counts_2[i] < 1200");
check(counts[i] > 800, "counts[i] > 800");
check(counts[i] > 800, "counts[i] > 800");
product += counts[i] * counts_2[i];
}
check(product < 256000000 * 1.001, "product < 256000000 * 1.001");
check(product > 256000000 * 0.999, "product > 256000000 * 0.999");
};
}

View file

@ -1,54 +0,0 @@
// Copyright (c) 2012, 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.
library test_sample_extension;
import 'sample_synchronous_extension.dart';
void check(bool condition, String message) {
if (!condition) {
throw new StateError(message);
}
}
void checkSystemRand() {
systemSrand(17);
var x1 = systemRand();
var x2 = systemRand();
var x3 = systemRand();
check(x1 != x2, "x1 != x2");
check(x1 != x3, "x1 != x3");
check(x2 != x3, "x2 != x3");
systemSrand(17);
check(x1 == systemRand(), "x1 == systemRand()");
check(x2 == systemRand(), "x2 == systemRand()");
check(x3 == systemRand(), "x3 == systemRand()");
systemSrand(18);
check(x1 != systemRand(), "x1 != systemRand()");
check(x2 != systemRand(), "x2 != systemRand()");
check(x3 != systemRand(), "x3 != systemRand()");
}
void checkNoScopeSystemRand() {
systemSrand(17);
var x1 = noScopeSystemRand();
var x2 = noScopeSystemRand();
var x3 = noScopeSystemRand();
check(x1 != x2, "x1 != x2");
check(x1 != x3, "x1 != x3");
check(x2 != x3, "x2 != x3");
systemSrand(17);
check(x1 == noScopeSystemRand(), "x1 == noScopeSystemRand()");
check(x2 == noScopeSystemRand(), "x2 == noScopeSystemRand()");
check(x3 == noScopeSystemRand(), "x3 == noScopeSystemRand()");
systemSrand(18);
check(x1 != noScopeSystemRand(), "x1 != noScopeSystemRand()");
check(x2 != noScopeSystemRand(), "x2 != noScopeSystemRand()");
check(x3 != noScopeSystemRand(), "x3 != noScopeSystemRand()");
}
void main() {
checkSystemRand();
checkNoScopeSystemRand();
}

View file

@ -1,9 +0,0 @@
/Makefile
/*.Makefile
/*.sln
/*.target.mk
/*.vcproj
/*.vcxproj
/*.vcxproj.filters
/*.vcxproj.user
/*.xcodeproj

View file

@ -1,13 +0,0 @@
This directory contains samples of native extensions.
To run the samples, first build both the Dart SDK and the runtime. For example:
```
$ ./tools/build.py create_sdk runtime
```
Then execute the sample programs. For example:
```
$ xcodebuild/ReleaseX64/dart samples/sample_extension/test/sample_extension_test.dart
```

View file

@ -1,44 +0,0 @@
// Copyright (c) 2012, 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.
// @dart = 2.9
library sample_asynchronous_extension;
import 'dart:async';
import 'dart:isolate';
import 'dart-ext:sample_extension';
// A class caches the native port used to call an asynchronous extension.
class RandomArray {
static SendPort _port;
Future<List<int>> randomArray(int seed, int length) {
var completer = new Completer<List<int>>();
var replyPort = new RawReceivePort();
var args = new List(3);
args[0] = seed;
args[1] = length;
args[2] = replyPort.sendPort;
_servicePort.send(args);
replyPort.handler = (result) {
replyPort.close();
if (result != null) {
completer.complete(result);
} else {
completer.completeError(new Exception("Random array creation failed"));
}
};
return completer.future;
}
SendPort get _servicePort {
if (_port == null) {
_port = _newServicePort();
}
return _port;
}
SendPort _newServicePort() native "RandomArray_ServicePort";
}

View file

@ -1,178 +0,0 @@
// Copyright (c) 2012, 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "include/dart_api.h"
#include "include/dart_native_api.h"
Dart_NativeFunction ResolveName(Dart_Handle name,
int argc,
bool* auto_setup_scope);
DART_EXPORT Dart_Handle sample_extension_Init(Dart_Handle parent_library) {
if (Dart_IsError(parent_library)) {
return parent_library;
}
Dart_Handle result_code =
Dart_SetNativeResolver(parent_library, ResolveName, NULL);
if (Dart_IsError(result_code)) {
return result_code;
}
return Dart_Null();
}
Dart_Handle HandleError(Dart_Handle handle) {
if (Dart_IsError(handle)) {
Dart_PropagateError(handle);
}
return handle;
}
void SystemRand(Dart_NativeArguments arguments) {
Dart_EnterScope();
Dart_Handle result = HandleError(Dart_NewInteger(rand()));
Dart_SetReturnValue(arguments, result);
Dart_ExitScope();
}
void SystemSrand(Dart_NativeArguments arguments) {
Dart_EnterScope();
bool success = false;
Dart_Handle seed_object = HandleError(Dart_GetNativeArgument(arguments, 0));
if (Dart_IsInteger(seed_object)) {
bool fits;
HandleError(Dart_IntegerFitsIntoInt64(seed_object, &fits));
if (fits) {
int64_t seed;
HandleError(Dart_IntegerToInt64(seed_object, &seed));
srand(static_cast<unsigned>(seed));
success = true;
}
}
Dart_SetReturnValue(arguments, HandleError(Dart_NewBoolean(success)));
Dart_ExitScope();
}
uint8_t* randomArray(int seed, int length) {
if (length <= 0 || length > 10000000) {
return NULL;
}
uint8_t* values = reinterpret_cast<uint8_t*>(malloc(length));
if (NULL == values) {
return NULL;
}
srand(seed);
for (int i = 0; i < length; ++i) {
values[i] = rand() % 256;
}
return values;
}
void wrappedRandomArray(Dart_Port dest_port_id, Dart_CObject* message) {
Dart_Port reply_port_id = ILLEGAL_PORT;
if (message->type == Dart_CObject_kArray &&
3 == message->value.as_array.length) {
// Use .as_array and .as_int32 to access the data in the Dart_CObject.
Dart_CObject* param0 = message->value.as_array.values[0];
Dart_CObject* param1 = message->value.as_array.values[1];
Dart_CObject* param2 = message->value.as_array.values[2];
if (param0->type == Dart_CObject_kInt32 &&
param1->type == Dart_CObject_kInt32 &&
param2->type == Dart_CObject_kSendPort) {
int seed = param0->value.as_int32;
int length = param1->value.as_int32;
reply_port_id = param2->value.as_send_port.id;
uint8_t* values = randomArray(seed, length);
if (values != NULL) {
Dart_CObject result;
result.type = Dart_CObject_kTypedData;
result.value.as_typed_data.type = Dart_TypedData_kUint8;
result.value.as_typed_data.values = values;
result.value.as_typed_data.length = length;
if (Dart_PostCObject(reply_port_id, &result)) {
Dart_CObject error;
error.type = Dart_CObject_kNull;
Dart_PostCObject(reply_port_id, &error);
}
free(values);
// It is OK that result is destroyed when function exits.
// Dart_PostCObject has copied its data.
return;
}
}
}
fprintf(stderr,
"Invalid message received, cannot proceed. Aborting the process.\n");
abort();
}
void randomArrayServicePort(Dart_NativeArguments arguments) {
Dart_EnterScope();
Dart_SetReturnValue(arguments, Dart_Null());
Dart_Port service_port =
Dart_NewNativePort("RandomArrayService", wrappedRandomArray, true);
if (service_port != ILLEGAL_PORT) {
Dart_Handle send_port = HandleError(Dart_NewSendPort(service_port));
Dart_SetReturnValue(arguments, send_port);
}
Dart_ExitScope();
}
struct FunctionLookup {
const char* name;
Dart_NativeFunction function;
};
FunctionLookup function_list[] = {
{"SystemRand", SystemRand},
{"SystemSrand", SystemSrand},
{"RandomArray_ServicePort", randomArrayServicePort},
{NULL, NULL}};
FunctionLookup no_scope_function_list[] = {{"NoScopeSystemRand", SystemRand},
{NULL, NULL}};
Dart_NativeFunction ResolveName(Dart_Handle name,
int argc,
bool* auto_setup_scope) {
if (!Dart_IsString(name)) {
return NULL;
}
Dart_NativeFunction result = NULL;
if (auto_setup_scope == NULL) {
return NULL;
}
Dart_EnterScope();
const char* cname;
HandleError(Dart_StringToCString(name, &cname));
for (int i = 0; function_list[i].name != NULL; ++i) {
if (strcmp(function_list[i].name, cname) == 0) {
*auto_setup_scope = true;
result = function_list[i].function;
break;
}
}
if (result != NULL) {
Dart_ExitScope();
return result;
}
for (int i = 0; no_scope_function_list[i].name != NULL; ++i) {
if (strcmp(no_scope_function_list[i].name, cname) == 0) {
*auto_setup_scope = false;
result = no_scope_function_list[i].function;
break;
}
}
Dart_ExitScope();
return result;
}

View file

@ -1,14 +0,0 @@
// Copyright (c) 2012, 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.
#if defined(_WIN32)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
BOOL APIENTRY DllMain(HMODULE module, DWORD reason, LPVOID reserved) {
return true;
}
#endif // defined(_WIN32)

View file

@ -1,14 +0,0 @@
// Copyright (c) 2012, 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.
// @dart = 2.9
library sample_synchronous_extension;
import 'dart-ext:sample_extension';
// The simplest way to call native code: top-level functions.
int systemRand() native "SystemRand";
int noScopeSystemRand() native "NoScopeSystemRand";
bool systemSrand(int seed) native "SystemSrand";

View file

@ -1,18 +0,0 @@
// 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.
//
// Dart test program for testing native extensions.
// @dart = 2.9
// OtherResources=../sample_synchronous_extension.dart
// OtherResources=../sample_asynchronous_extension.dart
// OtherResources=../test_sample_synchronous_extension.dart
// OtherResources=../test_sample_asynchronous_extension.dart
import 'sample_extension_test_helper.dart';
void main() {
testNativeExtensions("app-jit");
}

View file

@ -1,13 +0,0 @@
// 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.
//
// Dart test program for testing native extensions.
// @dart = 2.9
import 'sample_extension_test_helper.dart';
void main() {
testNativeExtensions(null /* no snapshot */);
}

View file

@ -1,116 +0,0 @@
// Copyright (c) 2013, 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.
//
// Dart test program for testing native extensions.
// @dart = 2.9
import 'dart:async';
import 'dart:io';
import 'dart:isolate';
import "package:expect/expect.dart";
import "package:path/path.dart";
Future copyFileToDirectory(String file, String directory) async {
String src = file;
String dst = directory;
ProcessResult result;
switch (Platform.operatingSystem) {
case 'linux':
case 'macos':
result = await Process.run('cp', [src, dst]);
break;
case 'windows':
result = await Process.run('cmd.exe', ['/C', 'copy $src $dst']);
break;
default:
throw 'Unknown operating system ${Platform.operatingSystem}';
}
if (result.exitCode != 0) {
print(result.stdout);
print(result.stderr);
throw "Failed to copy test file ($file) to temporary directory ($directory)";
}
}
Future run(String program, List<String> arguments) async {
print("+ $program ${arguments.join(' ')}");
ProcessResult result = await Process.run(program, arguments);
if (result.exitCode != 0) {
print('Failing process stdout: ${result.stdout}');
print('Failing process stderr: ${result.stderr}');
print('End failing process stderr');
Expect.fail('Test failed with exit code ${result.exitCode}');
}
}
Future runTests(
String program, String testDirectory, String snapshotKind) async {
for (var test in [
'test_sample_synchronous_extension.dart',
'test_sample_asynchronous_extension.dart'
]) {
String script = join(testDirectory, test);
String snapshot;
if (snapshotKind == null) {
snapshot = script;
} else {
snapshot = join(testDirectory, "$test.snapshot");
await run(Platform.executable, <String>[
...Platform.executableArguments,
'--snapshot=$snapshot',
'--snapshot-kind=$snapshotKind',
script
]);
}
await run(program, <String>[...Platform.executableArguments, snapshot]);
}
}
Future testNativeExtensions(String snapshotKind) async {
String buildDirectory = dirname(Platform.executable);
Directory tempDirectory =
Directory.systemTemp.createTempSync('sample_extension_');
try {
String testDirectory = tempDirectory.path;
String sourceDirectory = Platform.script.resolve('..').toFilePath();
// Copy sample_extension dart files and sample_extension tests to the
// temporary test directory.
for (var file in [
'sample_synchronous_extension.dart',
'sample_asynchronous_extension.dart',
'test_sample_synchronous_extension.dart',
'test_sample_asynchronous_extension.dart'
]) {
await copyFileToDirectory(join(sourceDirectory, file), testDirectory);
}
// Test native library resolution when it's next to the binary
await runTests(Platform.executable, testDirectory, snapshotKind);
// Test native library resolution when it's next to the source
await copyFileToDirectory(
join(
buildDirectory,
(Platform.isWindows ? '' : 'lib') +
'sample_extension' +
(Platform.isWindows
? '.dll'
: Platform.isMacOS
? '.dylib'
: '.so')),
testDirectory);
Directory tempBinDirectory = Directory(join(tempDirectory.path, 'dart-bin'))
..createSync();
await copyFileToDirectory(Platform.executable, tempBinDirectory.path);
String copyPlatformExecutable =
join(tempBinDirectory.path, basename(Platform.executable));
await runTests(copyPlatformExecutable, testDirectory, snapshotKind);
} finally {
tempDirectory.deleteSync(recursive: true);
}
}

View file

@ -1,60 +0,0 @@
// Copyright (c) 2012, 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.
// @dart = 2.9
library test_sample_extension;
import 'sample_asynchronous_extension.dart';
void check(bool condition, String message) {
if (!condition) {
throw new StateError(message);
}
}
void main() {
RandomArray r = new RandomArray();
r.randomArray(17, 100).then((list_100) {
r.randomArray(17, 200).then((list_200) {
for (var i = 0; i < 100; ++i) {
check(list_100[i] == list_200[i], "list_100[i] == list_200[i]");
}
});
});
// Gets a list of 256000 random uint8 values, using seed 19, and
// runs checkNormal on that list.
r.randomArray(19, 256000).then(checkNormal);
}
void checkNormal(List l) {
// Count how many times each byte value occurs. Assert that the counts
// are all within a reasonable (six-sigma) range.
List counts = new List<int>.filled(256, 0);
for (var e in l) {
counts[e]++;
}
new RandomArray().randomArray(18, 256000).then(checkCorrelation(counts));
}
Function checkCorrelation(List counts) {
return (List l) {
List counts_2 = new List<int>.filled(256, 0);
for (var e in l) {
counts_2[e]++;
}
var product = 0;
for (var i = 0; i < 256; ++i) {
check(counts[i] < 1200, "counts[i] < 1200");
check(counts_2[i] < 1200, "counts_2[i] < 1200");
check(counts[i] > 800, "counts[i] > 800");
check(counts[i] > 800, "counts[i] > 800");
product += counts[i] * counts_2[i];
}
check(product < 256000000 * 1.001, "product < 256000000 * 1.001");
check(product > 256000000 * 0.999, "product > 256000000 * 0.999");
};
}

View file

@ -1,56 +0,0 @@
// Copyright (c) 2012, 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.
// @dart = 2.9
library test_sample_extension;
import 'sample_synchronous_extension.dart';
void check(bool condition, String message) {
if (!condition) {
throw new StateError(message);
}
}
void checkSystemRand() {
systemSrand(17);
var x1 = systemRand();
var x2 = systemRand();
var x3 = systemRand();
check(x1 != x2, "x1 != x2");
check(x1 != x3, "x1 != x3");
check(x2 != x3, "x2 != x3");
systemSrand(17);
check(x1 == systemRand(), "x1 == systemRand()");
check(x2 == systemRand(), "x2 == systemRand()");
check(x3 == systemRand(), "x3 == systemRand()");
systemSrand(18);
check(x1 != systemRand(), "x1 != systemRand()");
check(x2 != systemRand(), "x2 != systemRand()");
check(x3 != systemRand(), "x3 != systemRand()");
}
void checkNoScopeSystemRand() {
systemSrand(17);
var x1 = noScopeSystemRand();
var x2 = noScopeSystemRand();
var x3 = noScopeSystemRand();
check(x1 != x2, "x1 != x2");
check(x1 != x3, "x1 != x3");
check(x2 != x3, "x2 != x3");
systemSrand(17);
check(x1 == noScopeSystemRand(), "x1 == noScopeSystemRand()");
check(x2 == noScopeSystemRand(), "x2 == noScopeSystemRand()");
check(x3 == noScopeSystemRand(), "x3 == noScopeSystemRand()");
systemSrand(18);
check(x1 != noScopeSystemRand(), "x1 != noScopeSystemRand()");
check(x2 != noScopeSystemRand(), "x2 != noScopeSystemRand()");
check(x3 != noScopeSystemRand(), "x3 != noScopeSystemRand()");
}
void main() {
checkSystemRand();
checkNoScopeSystemRand();
}

View file

@ -587,8 +587,8 @@ abstract class ZoneDelegate {
///
/// This is all handled internally by the platform code and most users don't need
/// to worry about it. However, developers of new asynchronous operations,
/// provided by the underlying system or through native extensions, must follow
/// the protocol to be zone compatible.
/// provided by the underlying system, must follow the protocol to be zone
/// compatible.
///
/// For convenience, zones provide [bindCallback] (and the corresponding
/// [bindUnaryCallback] and [bindBinaryCallback]) to make it easier to respect

View file

@ -1,20 +0,0 @@
// Copyright (c) 2012, 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.
library test_extension;
import "dart-ext:test_extension";
class Cat {
Cat(this.x);
num x;
String toString() => 'cat $x';
// Implements (a != null) ? a : b using a native C++ function and the API.
static int? ifNull(a, b) native 'TestExtension_IfNull';
static int throwMeTheBall(ball) native 'TestExtension_ThrowMeTheBall';
}

View file

@ -1,103 +0,0 @@
// Copyright (c) 2012, 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.
//
// Dart test program for testing native extensions.
// OtherResources=test_extension.dart
// OtherResources=test_extension_fail_tester.dart
// OtherResources=test_relative_extension.dart
// OtherResources=test_relative_extension_fail_tester.dart
import "package:path/path.dart";
import "dart:async";
import "dart:io";
Future copyFileToDirectory(String file, String directory) {
switch (Platform.operatingSystem) {
case 'linux':
case 'macos':
return Process.run('cp', [file, directory]);
case 'windows':
return Process.run('cmd.exe', ['/C', 'copy $file $directory']);
default:
throw new StateError(
'Unknown operating system ${Platform.operatingSystem}');
}
}
String getExtensionPath(String buildDirectory) {
switch (Platform.operatingSystem) {
case 'linux':
return join(buildDirectory, 'libtest_extension.so');
case 'macos':
return join(buildDirectory, 'libtest_extension.dylib');
case 'windows':
return join(buildDirectory, 'test_extension.dll');
default:
throw new StateError(
'Unknown operating system ${Platform.operatingSystem}');
}
}
bool checkExitCode(int code) {
return ((code == 255) || (code == 254) || (code == 253));
}
bool checkStdError(String err) {
return err.contains("Unhandled exception:") ||
err.contains(
"Native extension path must be absolute, or simply the file name");
}
// name is either "extension" or "relative_extension"
Future test(String name, bool checkForBall) async {
String scriptDirectory = dirname(Platform.script.toFilePath());
String buildDirectory = dirname(Platform.executable);
Directory tempDirectory =
Directory.systemTemp.createTempSync('dart_test_${name}_fail');
String testDirectory = tempDirectory.path;
// Copy test_extension shared library, test_extension.dart and
// test_extension_fail_tester.dart to the temporary test directory.
try {
if (name == "extension") {
print(getExtensionPath(buildDirectory));
await copyFileToDirectory(
getExtensionPath(buildDirectory), testDirectory);
} else {
var extensionDir = testDirectory + "/extension";
Directory dir = await (new Directory(extensionDir).create());
await copyFileToDirectory(getExtensionPath(buildDirectory), extensionDir);
}
var extensionDartFile = join(scriptDirectory, 'test_${name}.dart');
await copyFileToDirectory(extensionDartFile, testDirectory);
var testExtensionTesterFile =
join(scriptDirectory, 'test_${name}_fail_tester.dart');
await copyFileToDirectory(testExtensionTesterFile, testDirectory);
var args = new List<String>.from(Platform.executableArguments)
..add('--trace-loading')
..add(join(testDirectory, 'test_${name}_fail_tester.dart'));
var result = await Process.run(Platform.executable, args);
print("ERR: ${result.stderr}\n\n");
print("OUT: ${result.stdout}\n\n");
if (!checkExitCode(result.exitCode)) {
throw new StateError("bad exit code: ${result.exitCode}");
}
if (!checkStdError(result.stderr)) {
throw new StateError("stderr doesn't contain unhandled exception.");
}
if (checkForBall) {
if (!result.stderr.contains("ball")) {
throw new StateError("stderr doesn't contain 'ball'.");
}
}
} finally {
tempDirectory.deleteSync(recursive: true);
}
}
main() async {
await test("extension", true);
await test("relative_extension", false);
}

View file

@ -1,21 +0,0 @@
// Copyright (c) 2012, 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.
library test_extension_test;
import "dart:async";
import "dart:isolate";
import "test_extension.dart";
main() {
try {
Cat.throwMeTheBall("ball");
} on String catch (e) {
if (e != "ball") throw new StateError("exception not equal to 'ball'");
}
// Make sure the exception is thrown out to the event handler from C++ code.
// The harness expects the string "ball" to be thrown and the process to
// end with an unhandled exception.
Timer.run(() => Cat.throwMeTheBall("ball"));
}

View file

@ -1,117 +0,0 @@
// Copyright (c) 2012, 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.
//
// Dart test program for testing native extensions.
// OtherResources=test_extension.dart
// OtherResources=test_extension_tester.dart
import "package:expect/expect.dart";
import "package:path/path.dart";
import 'dart:async';
import 'dart:io';
import 'dart:isolate';
Future copyFileToDirectory(String file, String directory) {
switch (Platform.operatingSystem) {
case 'android':
case 'linux':
case 'macos':
return Process.run('cp', [file, directory]);
case 'windows':
return Process.run('cmd.exe', ['/C', 'copy $file $directory']);
default:
Expect.fail('Unknown operating system ${Platform.operatingSystem}');
}
throw 'Unknown operating system ${Platform.operatingSystem}';
}
// Returns a list containing the source file name in the first element and the
// target file name in the second element.
List<String> getExtensionNames(String arch) {
switch (Platform.operatingSystem) {
case 'android':
case 'linux':
return ['libtest_extension.so', 'libtest_extension$arch.so'];
case 'macos':
return ['libtest_extension.dylib', 'libtest_extension$arch.dylib'];
case 'windows':
return ['test_extension.dll', 'test_extension$arch.dll'];
default:
Expect.fail('Unknown operating system ${Platform.operatingSystem}');
}
throw 'Unknown operating system ${Platform.operatingSystem}';
}
String getExtensionPath(String buildDirectory, String filename) {
return join(buildDirectory, filename);
}
String getArchFromBuildDir(String buildDirectory) {
if (buildDirectory.endsWith('SIMARM')) return '';
if (buildDirectory.endsWith('SIMARM64')) return '';
if (buildDirectory.endsWith('ARM')) return '-arm';
if (buildDirectory.endsWith('ARM64')) return '-arm64';
if (buildDirectory.endsWith('IA32')) return '-ia32';
if (buildDirectory.endsWith('X64')) return '-x64';
return 'unknown';
}
Future testExtension(bool withArchSuffix) async {
String scriptDirectory = dirname(Platform.script.toFilePath());
String buildDirectory = dirname(Platform.executable);
Directory tempDirectory =
Directory.systemTemp.createTempSync('dart_test_extension');
String testDirectory = tempDirectory.path;
List<String> fileNames;
if (withArchSuffix) {
String arch = getArchFromBuildDir(buildDirectory);
fileNames = getExtensionNames(arch);
} else {
fileNames = getExtensionNames('');
}
try {
// Copy test_extension shared library, test_extension.dart and
// test_extension_tester.dart to the temporary test directory.
await copyFileToDirectory(getExtensionPath(buildDirectory, fileNames[0]),
join(testDirectory, fileNames[1]));
var extensionDartFile = join(scriptDirectory, 'test_extension.dart');
await copyFileToDirectory(extensionDartFile, testDirectory);
var testExtensionTesterFile =
join(scriptDirectory, 'test_extension_tester.dart');
await copyFileToDirectory(testExtensionTesterFile, testDirectory);
var args = new List<String>.from(Platform.executableArguments)
..add(join(testDirectory, 'test_extension_tester.dart'));
ProcessResult result = await Process.run(Platform.executable, args);
if (result.exitCode != 0) {
print('Subprocess failed with exit code ${result.exitCode}');
print('stdout:');
print('${result.stdout}');
print('stderr:');
print('${result.stderr}');
}
Expect.equals(0, result.exitCode);
} finally {
tempDirectory.deleteSync(recursive: true);
}
}
Future testWithArchSuffix() {
return testExtension(true);
}
Future testWithoutArchSuffix() {
return testExtension(false);
}
main() async {
await testWithArchSuffix();
await testWithoutArchSuffix();
}

View file

@ -1,47 +0,0 @@
// Copyright (c) 2012, 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.
// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
library test_extension_test;
import 'dart:isolate';
import "test_extension.dart";
class Expect {
static void equals(expected, actual, [msg]) {
if (expected != actual) {
if (msg == null) msg = "Expected: $expected. Actual: $actual";
throw new StateError(msg);
}
}
static void isNull(x, [msg]) {
if (x != null) {
if (msg != null) msg = "$x not null";
throw new StateError(msg);
}
}
}
isolateHandler(_) {}
main() async {
Expect.equals('cat 13', new Cat(13).toString(), 'new Cat(13).toString()');
Expect.equals(3, Cat.ifNull(null, 3), 'Cat.ifNull(null, 3)');
Expect.equals(4, Cat.ifNull(4, null), 'Cat.ifNull(4, null)');
Expect.equals(5, Cat.ifNull(5, 9), 'Cat.ifNull(5, 9)');
Expect.isNull(Cat.ifNull(null, null), 'Cat.ifNull(null, null)');
try {
Cat.throwMeTheBall("ball");
} on String catch (e) {
Expect.equals("ball", e);
}
await Isolate.spawn(isolateHandler, []);
}

View file

@ -1,20 +0,0 @@
// 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.
library test_extension;
import "dart-ext:extension/test_extension";
class Cat {
Cat(this.x);
num x;
String toString() => 'cat $x';
// Implements (a != null) ? a : b using a native C++ function and the API.
static int ifNull(a, b) native 'TestExtension_IfNull';
static int throwMeTheBall(ball) native 'TestExtension_ThrowMeTheBall';
}

View file

@ -1,22 +0,0 @@
// Copyright (c) 2012, 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.
// @dart = 2.9
library test_extension;
import "dart-ext:test_extension";
class Cat {
Cat(this.x);
num x;
String toString() => 'cat $x';
// Implements (a != null) ? a : b using a native C++ function and the API.
static int ifNull(a, b) native 'TestExtension_IfNull';
static int throwMeTheBall(ball) native 'TestExtension_ThrowMeTheBall';
}

View file

@ -1,105 +0,0 @@
// Copyright (c) 2012, 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.
//
// Dart test program for testing native extensions.
// @dart = 2.9
// OtherResources=test_extension.dart
// OtherResources=test_extension_fail_tester.dart
// OtherResources=test_relative_extension.dart
// OtherResources=test_relative_extension_fail_tester.dart
import "package:path/path.dart";
import "dart:async";
import "dart:io";
Future copyFileToDirectory(String file, String directory) {
switch (Platform.operatingSystem) {
case 'linux':
case 'macos':
return Process.run('cp', [file, directory]);
case 'windows':
return Process.run('cmd.exe', ['/C', 'copy $file $directory']);
default:
throw new StateError(
'Unknown operating system ${Platform.operatingSystem}');
}
}
String getExtensionPath(String buildDirectory) {
switch (Platform.operatingSystem) {
case 'linux':
return join(buildDirectory, 'libtest_extension.so');
case 'macos':
return join(buildDirectory, 'libtest_extension.dylib');
case 'windows':
return join(buildDirectory, 'test_extension.dll');
default:
throw new StateError(
'Unknown operating system ${Platform.operatingSystem}');
}
}
bool checkExitCode(int code) {
return ((code == 255) || (code == 254) || (code == 253));
}
bool checkStdError(String err) {
return err.contains("Unhandled exception:") ||
err.contains(
"Native extension path must be absolute, or simply the file name");
}
// name is either "extension" or "relative_extension"
Future test(String name, bool checkForBall) async {
String scriptDirectory = dirname(Platform.script.toFilePath());
String buildDirectory = dirname(Platform.executable);
Directory tempDirectory =
Directory.systemTemp.createTempSync('dart_test_${name}_fail');
String testDirectory = tempDirectory.path;
// Copy test_extension shared library, test_extension.dart and
// test_extension_fail_tester.dart to the temporary test directory.
try {
if (name == "extension") {
print(getExtensionPath(buildDirectory));
await copyFileToDirectory(
getExtensionPath(buildDirectory), testDirectory);
} else {
var extensionDir = testDirectory + "/extension";
Directory dir = await (new Directory(extensionDir).create());
await copyFileToDirectory(getExtensionPath(buildDirectory), extensionDir);
}
var extensionDartFile = join(scriptDirectory, 'test_${name}.dart');
await copyFileToDirectory(extensionDartFile, testDirectory);
var testExtensionTesterFile =
join(scriptDirectory, 'test_${name}_fail_tester.dart');
await copyFileToDirectory(testExtensionTesterFile, testDirectory);
var args = new List<String>.from(Platform.executableArguments)
..add('--trace-loading')
..add(join(testDirectory, 'test_${name}_fail_tester.dart'));
var result = await Process.run(Platform.executable, args);
print("ERR: ${result.stderr}\n\n");
print("OUT: ${result.stdout}\n\n");
if (!checkExitCode(result.exitCode)) {
throw new StateError("bad exit code: ${result.exitCode}");
}
if (!checkStdError(result.stderr)) {
throw new StateError("stderr doesn't contain unhandled exception.");
}
if (checkForBall) {
if (!result.stderr.contains("ball")) {
throw new StateError("stderr doesn't contain 'ball'.");
}
}
} finally {
tempDirectory.deleteSync(recursive: true);
}
}
main() async {
await test("extension", true);
await test("relative_extension", false);
}

View file

@ -1,23 +0,0 @@
// Copyright (c) 2012, 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.
// @dart = 2.9
library test_extension_test;
import "dart:async";
import "dart:isolate";
import "test_extension.dart";
main() {
try {
Cat.throwMeTheBall("ball");
} on String catch (e) {
if (e != "ball") throw new StateError("exception not equal to 'ball'");
}
// Make sure the exception is thrown out to the event handler from C++ code.
// The harness expects the string "ball" to be thrown and the process to
// end with an unhandled exception.
Timer.run(() => Cat.throwMeTheBall("ball"));
}

View file

@ -1,119 +0,0 @@
// Copyright (c) 2012, 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.
//
// Dart test program for testing native extensions.
// @dart = 2.9
// OtherResources=test_extension.dart
// OtherResources=test_extension_tester.dart
import "package:expect/expect.dart";
import "package:path/path.dart";
import 'dart:async';
import 'dart:io';
import 'dart:isolate';
Future copyFileToDirectory(String file, String directory) {
switch (Platform.operatingSystem) {
case 'android':
case 'linux':
case 'macos':
return Process.run('cp', [file, directory]);
case 'windows':
return Process.run('cmd.exe', ['/C', 'copy $file $directory']);
default:
Expect.fail('Unknown operating system ${Platform.operatingSystem}');
}
throw 'Unknown operating system ${Platform.operatingSystem}';
}
// Returns a list containing the source file name in the first element and the
// target file name in the second element.
List<String> getExtensionNames(String arch) {
switch (Platform.operatingSystem) {
case 'android':
case 'linux':
return ['libtest_extension.so', 'libtest_extension$arch.so'];
case 'macos':
return ['libtest_extension.dylib', 'libtest_extension$arch.dylib'];
case 'windows':
return ['test_extension.dll', 'test_extension$arch.dll'];
default:
Expect.fail('Unknown operating system ${Platform.operatingSystem}');
}
throw 'Unknown operating system ${Platform.operatingSystem}';
}
String getExtensionPath(String buildDirectory, String filename) {
return join(buildDirectory, filename);
}
String getArchFromBuildDir(String buildDirectory) {
if (buildDirectory.endsWith('SIMARM')) return '';
if (buildDirectory.endsWith('SIMARM64')) return '';
if (buildDirectory.endsWith('ARM')) return '-arm';
if (buildDirectory.endsWith('ARM64')) return '-arm64';
if (buildDirectory.endsWith('IA32')) return '-ia32';
if (buildDirectory.endsWith('X64')) return '-x64';
return 'unknown';
}
Future testExtension(bool withArchSuffix) async {
String scriptDirectory = dirname(Platform.script.toFilePath());
String buildDirectory = dirname(Platform.executable);
Directory tempDirectory =
Directory.systemTemp.createTempSync('dart_test_extension');
String testDirectory = tempDirectory.path;
List<String> fileNames;
if (withArchSuffix) {
String arch = getArchFromBuildDir(buildDirectory);
fileNames = getExtensionNames(arch);
} else {
fileNames = getExtensionNames('');
}
try {
// Copy test_extension shared library, test_extension.dart and
// test_extension_tester.dart to the temporary test directory.
await copyFileToDirectory(getExtensionPath(buildDirectory, fileNames[0]),
join(testDirectory, fileNames[1]));
var extensionDartFile = join(scriptDirectory, 'test_extension.dart');
await copyFileToDirectory(extensionDartFile, testDirectory);
var testExtensionTesterFile =
join(scriptDirectory, 'test_extension_tester.dart');
await copyFileToDirectory(testExtensionTesterFile, testDirectory);
var args = new List<String>.from(Platform.executableArguments)
..add(join(testDirectory, 'test_extension_tester.dart'));
ProcessResult result = await Process.run(Platform.executable, args);
if (result.exitCode != 0) {
print('Subprocess failed with exit code ${result.exitCode}');
print('stdout:');
print('${result.stdout}');
print('stderr:');
print('${result.stderr}');
}
Expect.equals(0, result.exitCode);
} finally {
tempDirectory.deleteSync(recursive: true);
}
}
Future testWithArchSuffix() {
return testExtension(true);
}
Future testWithoutArchSuffix() {
return testExtension(false);
}
main() async {
await testWithArchSuffix();
await testWithoutArchSuffix();
}

View file

@ -1,49 +0,0 @@
// Copyright (c) 2012, 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.
// @dart = 2.9
// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
library test_extension_test;
import 'dart:isolate';
import "test_extension.dart";
class Expect {
static void equals(expected, actual, [msg]) {
if (expected != actual) {
if (msg == null) msg = "Expected: $expected. Actual: $actual";
throw new StateError(msg);
}
}
static void isNull(x, [msg]) {
if (x != null) {
if (msg != null) msg = "$x not null";
throw new StateError(msg);
}
}
}
isolateHandler(_) {}
main() async {
Expect.equals('cat 13', new Cat(13).toString(), 'new Cat(13).toString()');
Expect.equals(3, Cat.ifNull(null, 3), 'Cat.ifNull(null, 3)');
Expect.equals(4, Cat.ifNull(4, null), 'Cat.ifNull(4, null)');
Expect.equals(5, Cat.ifNull(5, 9), 'Cat.ifNull(5, 9)');
Expect.isNull(Cat.ifNull(null, null), 'Cat.ifNull(null, null)');
try {
Cat.throwMeTheBall("ball");
} on String catch (e) {
Expect.equals("ball", e);
}
await Isolate.spawn(isolateHandler, []);
}

View file

@ -1,22 +0,0 @@
// 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.
// @dart = 2.9
library test_extension;
import "dart-ext:extension/test_extension";
class Cat {
Cat(this.x);
num x;
String toString() => 'cat $x';
// Implements (a != null) ? a : b using a native C++ function and the API.
static int ifNull(a, b) native 'TestExtension_IfNull';
static int throwMeTheBall(ball) native 'TestExtension_ThrowMeTheBall';
}