2012-01-10 16:50:14 +00:00
|
|
|
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
|
2011-10-05 05:20:07 +00:00
|
|
|
// 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/dartutils.h"
|
|
|
|
|
2013-05-08 16:42:46 +00:00
|
|
|
#include "include/dart_api.h"
|
2013-06-14 23:47:40 +00:00
|
|
|
#include "include/dart_native_api.h"
|
2013-05-08 16:42:46 +00:00
|
|
|
|
|
|
|
#include "platform/assert.h"
|
|
|
|
#include "platform/globals.h"
|
|
|
|
|
2013-11-06 00:59:46 +00:00
|
|
|
#include "bin/crypto.h"
|
2012-09-04 20:46:30 +00:00
|
|
|
#include "bin/directory.h"
|
2013-11-06 00:59:46 +00:00
|
|
|
#include "bin/extensions.h"
|
2011-11-18 18:24:04 +00:00
|
|
|
#include "bin/file.h"
|
2012-12-06 13:44:24 +00:00
|
|
|
#include "bin/io_buffer.h"
|
2013-05-29 14:34:15 +00:00
|
|
|
#include "bin/socket.h"
|
2013-11-06 00:59:46 +00:00
|
|
|
#include "bin/utils.h"
|
2011-11-18 18:24:04 +00:00
|
|
|
|
2013-04-25 14:22:30 +00:00
|
|
|
namespace dart {
|
|
|
|
namespace bin {
|
|
|
|
|
2012-09-04 20:46:30 +00:00
|
|
|
const char* DartUtils::original_working_directory = NULL;
|
2011-11-18 18:24:04 +00:00
|
|
|
const char* DartUtils::kDartScheme = "dart:";
|
2012-02-23 13:25:11 +00:00
|
|
|
const char* DartUtils::kDartExtensionScheme = "dart-ext:";
|
2013-02-25 23:25:29 +00:00
|
|
|
const char* DartUtils::kAsyncLibURL = "dart:async";
|
2014-06-13 22:43:31 +00:00
|
|
|
const char* DartUtils::kBuiltinLibURL = "dart:_builtin";
|
2011-11-17 21:04:43 +00:00
|
|
|
const char* DartUtils::kCoreLibURL = "dart:core";
|
2014-01-16 12:06:38 +00:00
|
|
|
const char* DartUtils::kInternalLibURL = "dart:_internal";
|
2013-12-02 16:27:07 +00:00
|
|
|
const char* DartUtils::kIsolateLibURL = "dart:isolate";
|
2012-01-24 07:36:59 +00:00
|
|
|
const char* DartUtils::kIOLibURL = "dart:io";
|
2012-10-30 10:32:30 +00:00
|
|
|
const char* DartUtils::kIOLibPatchURL = "dart:io-patch";
|
2013-05-29 14:34:15 +00:00
|
|
|
const char* DartUtils::kUriLibURL = "dart:uri";
|
|
|
|
const char* DartUtils::kHttpScheme = "http:";
|
2014-01-14 22:34:43 +00:00
|
|
|
const char* DartUtils::kVMServiceLibURL = "dart:vmservice";
|
2012-01-24 07:36:59 +00:00
|
|
|
|
2013-03-21 18:47:49 +00:00
|
|
|
uint8_t DartUtils::magic_number[] = { 0xf5, 0xf5, 0xdc, 0xdc };
|
2011-10-05 05:20:07 +00:00
|
|
|
|
2012-09-04 20:46:30 +00:00
|
|
|
static bool IsWindowsHost() {
|
|
|
|
#if defined(TARGET_OS_WINDOWS)
|
|
|
|
return true;
|
|
|
|
#else // defined(TARGET_OS_WINDOWS)
|
|
|
|
return false;
|
|
|
|
#endif // defined(TARGET_OS_WINDOWS)
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-12-04 20:27:00 +00:00
|
|
|
const char* DartUtils::MapLibraryUrl(CommandLineOptions* url_mapping,
|
|
|
|
const char* url_string) {
|
2011-11-18 18:24:04 +00:00
|
|
|
ASSERT(url_mapping != NULL);
|
|
|
|
// We need to check if the passed in url is found in the url_mapping array,
|
|
|
|
// in that case use the mapped entry.
|
2013-10-07 20:19:37 +00:00
|
|
|
intptr_t len = strlen(url_string);
|
|
|
|
for (intptr_t idx = 0; idx < url_mapping->count(); idx++) {
|
2011-11-18 18:24:04 +00:00
|
|
|
const char* url_name = url_mapping->GetArgument(idx);
|
|
|
|
if (!strncmp(url_string, url_name, len) && (url_name[len] == ',')) {
|
|
|
|
const char* url_mapped_name = url_name + len + 1;
|
|
|
|
if (strlen(url_mapped_name) != 0) {
|
|
|
|
return url_mapped_name; // Found a mapping for this URL.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL; // Did not find a mapping for this URL.
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-10-05 05:20:07 +00:00
|
|
|
int64_t DartUtils::GetIntegerValue(Dart_Handle value_obj) {
|
2011-10-26 20:38:41 +00:00
|
|
|
int64_t value = 0;
|
2011-12-09 17:25:44 +00:00
|
|
|
Dart_Handle result = Dart_IntegerToInt64(value_obj, &value);
|
2013-11-27 11:46:20 +00:00
|
|
|
if (Dart_IsError(result)) Dart_PropagateError(result);
|
2011-10-26 20:38:41 +00:00
|
|
|
return value;
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
2011-11-17 21:04:43 +00:00
|
|
|
|
2013-11-27 12:12:08 +00:00
|
|
|
int64_t DartUtils::GetInt64ValueCheckRange(
|
|
|
|
Dart_Handle value_obj, int64_t lower, int64_t upper) {
|
|
|
|
int64_t value = DartUtils::GetIntegerValue(value_obj);
|
|
|
|
if (value < lower || upper < value) {
|
|
|
|
Dart_PropagateError(Dart_NewApiError("Value outside expected range"));
|
|
|
|
}
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-12-03 14:39:05 +00:00
|
|
|
intptr_t DartUtils::GetIntptrValue(Dart_Handle value_obj) {
|
|
|
|
int64_t value = 0;
|
|
|
|
Dart_Handle result = Dart_IntegerToInt64(value_obj, &value);
|
2013-11-27 11:46:20 +00:00
|
|
|
if (Dart_IsError(result)) Dart_PropagateError(result);
|
|
|
|
if (value < kIntptrMin || kIntptrMax < value) {
|
2013-11-27 12:12:08 +00:00
|
|
|
Dart_PropagateError(Dart_NewApiError("Value outside intptr_t range"));
|
2013-11-27 11:46:20 +00:00
|
|
|
}
|
2012-12-03 14:39:05 +00:00
|
|
|
return static_cast<intptr_t>(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-05-21 10:52:01 +00:00
|
|
|
bool DartUtils::GetInt64Value(Dart_Handle value_obj, int64_t* value) {
|
|
|
|
bool valid = Dart_IsInteger(value_obj);
|
|
|
|
if (valid) {
|
|
|
|
Dart_Handle result = Dart_IntegerFitsIntoInt64(value_obj, &valid);
|
2013-11-27 11:46:20 +00:00
|
|
|
if (Dart_IsError(result)) Dart_PropagateError(result);
|
2012-05-21 10:52:01 +00:00
|
|
|
}
|
|
|
|
if (!valid) return false;
|
|
|
|
Dart_Handle result = Dart_IntegerToInt64(value_obj, value);
|
2013-11-27 11:46:20 +00:00
|
|
|
if (Dart_IsError(result)) Dart_PropagateError(result);
|
2012-05-21 10:52:01 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-10-05 05:20:07 +00:00
|
|
|
const char* DartUtils::GetStringValue(Dart_Handle str_obj) {
|
2011-10-26 20:38:41 +00:00
|
|
|
const char* cstring = NULL;
|
|
|
|
Dart_Handle result = Dart_StringToCString(str_obj, &cstring);
|
2013-11-27 11:46:20 +00:00
|
|
|
if (Dart_IsError(result)) Dart_PropagateError(result);
|
2011-10-26 20:38:41 +00:00
|
|
|
return cstring;
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool DartUtils::GetBooleanValue(Dart_Handle bool_obj) {
|
2011-10-26 20:38:41 +00:00
|
|
|
bool value = false;
|
|
|
|
Dart_Handle result = Dart_BooleanValue(bool_obj, &value);
|
2013-11-27 11:46:20 +00:00
|
|
|
if (Dart_IsError(result)) Dart_PropagateError(result);
|
2011-10-26 20:38:41 +00:00
|
|
|
return value;
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
2011-11-17 21:04:43 +00:00
|
|
|
|
2012-03-08 18:36:56 +00:00
|
|
|
void DartUtils::SetIntegerField(Dart_Handle handle,
|
|
|
|
const char* name,
|
2014-01-16 05:05:35 +00:00
|
|
|
int64_t val) {
|
2012-03-08 18:36:56 +00:00
|
|
|
Dart_Handle result = Dart_SetField(handle,
|
2012-10-31 17:56:46 +00:00
|
|
|
NewString(name),
|
2012-03-08 18:36:56 +00:00
|
|
|
Dart_NewInteger(val));
|
2013-11-27 11:46:20 +00:00
|
|
|
if (Dart_IsError(result)) Dart_PropagateError(result);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
2011-11-17 21:04:43 +00:00
|
|
|
|
2012-03-08 18:36:56 +00:00
|
|
|
void DartUtils::SetStringField(Dart_Handle handle,
|
|
|
|
const char* name,
|
|
|
|
const char* val) {
|
2012-10-31 17:56:46 +00:00
|
|
|
Dart_Handle result = Dart_SetField(handle, NewString(name), NewString(val));
|
2013-11-27 11:46:20 +00:00
|
|
|
if (Dart_IsError(result)) Dart_PropagateError(result);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
2011-11-18 18:24:04 +00:00
|
|
|
|
|
|
|
|
|
|
|
bool DartUtils::IsDartSchemeURL(const char* url_name) {
|
|
|
|
static const intptr_t kDartSchemeLen = strlen(kDartScheme);
|
|
|
|
// If the URL starts with "dart:" then it is considered as a special
|
|
|
|
// library URL which is handled differently from other URLs.
|
|
|
|
return (strncmp(url_name, kDartScheme, kDartSchemeLen) == 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-05-29 14:34:15 +00:00
|
|
|
bool DartUtils::IsHttpSchemeURL(const char* url_name) {
|
|
|
|
static const intptr_t kHttpSchemeLen = strlen(kHttpScheme);
|
|
|
|
return (strncmp(url_name, kHttpScheme, kHttpSchemeLen) == 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-02-23 13:25:11 +00:00
|
|
|
bool DartUtils::IsDartExtensionSchemeURL(const char* url_name) {
|
|
|
|
static const intptr_t kDartExtensionSchemeLen = strlen(kDartExtensionScheme);
|
|
|
|
// If the URL starts with "dartext:" then it is considered as a special
|
|
|
|
// extension library URL which is handled differently from other URLs.
|
|
|
|
return
|
|
|
|
(strncmp(url_name, kDartExtensionScheme, kDartExtensionSchemeLen) == 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-01-24 07:36:59 +00:00
|
|
|
bool DartUtils::IsDartIOLibURL(const char* url_name) {
|
|
|
|
return (strcmp(url_name, kIOLibURL) == 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-02-12 02:39:00 +00:00
|
|
|
bool DartUtils::IsDartBuiltinLibURL(const char* url_name) {
|
|
|
|
return (strcmp(url_name, kBuiltinLibURL) == 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-05-03 22:50:26 +00:00
|
|
|
void* DartUtils::OpenFile(const char* name, bool write) {
|
|
|
|
File* file = File::Open(name, write ? File::kWriteTruncate : File::kRead);
|
|
|
|
return reinterpret_cast<void*>(file);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DartUtils::ReadFile(const uint8_t** data,
|
2014-01-16 05:05:35 +00:00
|
|
|
intptr_t* len,
|
2013-05-03 22:50:26 +00:00
|
|
|
void* stream) {
|
|
|
|
ASSERT(data != NULL);
|
2014-01-16 05:05:35 +00:00
|
|
|
ASSERT(len != NULL);
|
2013-05-03 22:50:26 +00:00
|
|
|
ASSERT(stream != NULL);
|
|
|
|
File* file_stream = reinterpret_cast<File*>(stream);
|
2014-01-16 05:05:35 +00:00
|
|
|
int64_t file_len = file_stream->Length();
|
|
|
|
if ((file_len < 0) || (file_len > kIntptrMax)) {
|
|
|
|
*data = NULL;
|
|
|
|
*len = -1; // Indicates read was not successful.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
*len = static_cast<intptr_t>(file_len);
|
|
|
|
uint8_t* text_buffer = reinterpret_cast<uint8_t*>(malloc(*len));
|
2013-05-03 22:50:26 +00:00
|
|
|
ASSERT(text_buffer != NULL);
|
2014-01-16 05:05:35 +00:00
|
|
|
if (!file_stream->ReadFully(text_buffer, *len)) {
|
2013-05-03 22:50:26 +00:00
|
|
|
*data = NULL;
|
2014-01-16 05:05:35 +00:00
|
|
|
*len = -1; // Indicates read was not successful.
|
2013-05-03 22:50:26 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
*data = text_buffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DartUtils::WriteFile(const void* buffer,
|
|
|
|
intptr_t num_bytes,
|
|
|
|
void* stream) {
|
|
|
|
ASSERT(stream != NULL);
|
|
|
|
File* file_stream = reinterpret_cast<File*>(stream);
|
|
|
|
bool bytes_written = file_stream->WriteFully(buffer, num_bytes);
|
|
|
|
ASSERT(bytes_written);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DartUtils::CloseFile(void* stream) {
|
|
|
|
delete reinterpret_cast<File*>(stream);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-11-06 01:08:22 +00:00
|
|
|
bool DartUtils::EntropySource(uint8_t* buffer, intptr_t length) {
|
2013-11-06 00:59:46 +00:00
|
|
|
return Crypto::GetRandomBytes(length, buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-06-19 00:02:38 +00:00
|
|
|
static Dart_Handle SingleArgDart_Invoke(Dart_Handle lib, const char* method,
|
|
|
|
Dart_Handle arg) {
|
2013-06-17 16:38:17 +00:00
|
|
|
const int kNumArgs = 1;
|
|
|
|
Dart_Handle dart_args[kNumArgs];
|
|
|
|
dart_args[0] = arg;
|
|
|
|
return Dart_Invoke(lib, DartUtils::NewString(method), kNumArgs, dart_args);
|
2013-05-29 14:34:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// TODO(iposva): Allocate from the zone instead of leaking error string
|
2013-06-25 13:54:42 +00:00
|
|
|
// here. On the other hand the binary is about to exit anyway.
|
2013-05-29 14:34:15 +00:00
|
|
|
#define SET_ERROR_MSG(error_msg, format, ...) \
|
|
|
|
intptr_t len = snprintf(NULL, 0, format, __VA_ARGS__); \
|
2013-06-25 13:54:42 +00:00
|
|
|
char* msg = reinterpret_cast<char*>(malloc(len + 1)); \
|
2013-05-29 14:34:15 +00:00
|
|
|
snprintf(msg, len + 1, format, __VA_ARGS__); \
|
|
|
|
*error_msg = msg
|
|
|
|
|
|
|
|
|
2013-05-03 22:50:26 +00:00
|
|
|
static const uint8_t* ReadFileFully(const char* filename,
|
|
|
|
intptr_t* file_len,
|
|
|
|
const char** error_msg) {
|
2013-08-07 17:28:04 +00:00
|
|
|
*file_len = -1;
|
2013-05-03 22:50:26 +00:00
|
|
|
void* stream = DartUtils::OpenFile(filename, false);
|
|
|
|
if (stream == NULL) {
|
2013-05-29 14:34:15 +00:00
|
|
|
SET_ERROR_MSG(error_msg, "Unable to open file: %s", filename);
|
2013-03-21 18:47:49 +00:00
|
|
|
return NULL;
|
2011-11-18 18:24:04 +00:00
|
|
|
}
|
2013-05-03 22:50:26 +00:00
|
|
|
const uint8_t* text_buffer = NULL;
|
|
|
|
DartUtils::ReadFile(&text_buffer, file_len, stream);
|
|
|
|
if (text_buffer == NULL || *file_len == -1) {
|
|
|
|
*error_msg = "Unable to read file contents";
|
|
|
|
text_buffer = NULL;
|
2011-11-18 18:24:04 +00:00
|
|
|
}
|
2013-05-03 22:50:26 +00:00
|
|
|
DartUtils::CloseFile(stream);
|
2013-03-21 18:47:49 +00:00
|
|
|
return text_buffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Dart_Handle DartUtils::ReadStringFromFile(const char* filename) {
|
|
|
|
const char* error_msg = NULL;
|
|
|
|
intptr_t len;
|
2013-05-03 22:50:26 +00:00
|
|
|
const uint8_t* text_buffer = ReadFileFully(filename, &len, &error_msg);
|
2013-03-21 18:47:49 +00:00
|
|
|
if (text_buffer == NULL) {
|
2013-10-17 17:49:45 +00:00
|
|
|
return Dart_NewApiError(error_msg);
|
2013-03-21 18:47:49 +00:00
|
|
|
}
|
2012-10-31 17:56:46 +00:00
|
|
|
Dart_Handle str = Dart_NewStringFromUTF8(text_buffer, len);
|
2013-07-30 07:13:33 +00:00
|
|
|
free(const_cast<uint8_t *>(text_buffer));
|
2011-11-18 18:24:04 +00:00
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-06-19 00:02:38 +00:00
|
|
|
Dart_Handle DartUtils::SetWorkingDirectory(Dart_Handle builtin_lib) {
|
|
|
|
Dart_Handle directory = NewString(original_working_directory);
|
|
|
|
return SingleArgDart_Invoke(builtin_lib, "_setWorkingDirectory", directory);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-12-04 20:27:00 +00:00
|
|
|
Dart_Handle DartUtils::ResolveScriptUri(Dart_Handle script_uri,
|
|
|
|
Dart_Handle builtin_lib) {
|
2013-06-19 00:02:38 +00:00
|
|
|
const int kNumArgs = 1;
|
2013-06-17 16:38:17 +00:00
|
|
|
Dart_Handle dart_args[kNumArgs];
|
2013-06-19 00:02:38 +00:00
|
|
|
dart_args[0] = script_uri;
|
2013-06-17 16:38:17 +00:00
|
|
|
return Dart_Invoke(builtin_lib,
|
|
|
|
NewString("_resolveScriptUri"),
|
|
|
|
kNumArgs,
|
|
|
|
dart_args);
|
2012-09-04 20:46:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-12-04 20:27:00 +00:00
|
|
|
Dart_Handle DartUtils::FilePathFromUri(Dart_Handle script_uri,
|
|
|
|
Dart_Handle builtin_lib) {
|
2013-06-19 00:02:38 +00:00
|
|
|
const int kNumArgs = 1;
|
2013-06-17 16:38:17 +00:00
|
|
|
Dart_Handle dart_args[kNumArgs];
|
|
|
|
dart_args[0] = script_uri;
|
|
|
|
return Dart_Invoke(builtin_lib,
|
|
|
|
NewString("_filePathFromUri"),
|
|
|
|
kNumArgs,
|
|
|
|
dart_args);
|
2012-12-04 20:27:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-03-04 14:39:12 +00:00
|
|
|
Dart_Handle DartUtils::ExtensionPathFromUri(Dart_Handle extension_uri,
|
|
|
|
Dart_Handle builtin_lib) {
|
|
|
|
const int kNumArgs = 1;
|
|
|
|
Dart_Handle dart_args[kNumArgs];
|
|
|
|
dart_args[0] = extension_uri;
|
|
|
|
return Dart_Invoke(builtin_lib,
|
|
|
|
NewString("_extensionPathFromUri"),
|
|
|
|
kNumArgs,
|
|
|
|
dart_args);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-12-04 20:27:00 +00:00
|
|
|
Dart_Handle DartUtils::ResolveUri(Dart_Handle library_url,
|
|
|
|
Dart_Handle url,
|
|
|
|
Dart_Handle builtin_lib) {
|
|
|
|
const int kNumArgs = 2;
|
|
|
|
Dart_Handle dart_args[kNumArgs];
|
|
|
|
dart_args[0] = library_url;
|
|
|
|
dart_args[1] = url;
|
|
|
|
return Dart_Invoke(
|
|
|
|
builtin_lib, NewString("_resolveUri"), kNumArgs, dart_args);
|
2012-09-04 20:46:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-09-04 06:42:01 +00:00
|
|
|
static Dart_Handle LoadDataAsync_Invoke(Dart_Handle tag,
|
|
|
|
Dart_Handle url,
|
|
|
|
Dart_Handle library_url,
|
|
|
|
Dart_Handle builtin_lib) {
|
|
|
|
const int kNumArgs = 3;
|
|
|
|
Dart_Handle dart_args[kNumArgs];
|
|
|
|
dart_args[0] = tag;
|
|
|
|
dart_args[1] = url;
|
|
|
|
dart_args[2] = library_url;
|
|
|
|
return Dart_Invoke(builtin_lib,
|
|
|
|
DartUtils::NewString("_loadDataAsync"),
|
|
|
|
kNumArgs,
|
|
|
|
dart_args);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-04 20:46:30 +00:00
|
|
|
Dart_Handle DartUtils::LibraryTagHandler(Dart_LibraryTag tag,
|
|
|
|
Dart_Handle library,
|
|
|
|
Dart_Handle url) {
|
|
|
|
if (!Dart_IsLibrary(library)) {
|
2013-10-17 17:49:45 +00:00
|
|
|
return Dart_NewApiError("not a library");
|
2012-09-04 20:46:30 +00:00
|
|
|
}
|
2012-10-31 17:56:46 +00:00
|
|
|
if (!Dart_IsString(url)) {
|
2013-10-17 17:49:45 +00:00
|
|
|
return Dart_NewApiError("url is not a string");
|
2012-09-04 20:46:30 +00:00
|
|
|
}
|
|
|
|
const char* url_string = NULL;
|
|
|
|
Dart_Handle result = Dart_StringToCString(url, &url_string);
|
|
|
|
if (Dart_IsError(result)) {
|
|
|
|
return result;
|
|
|
|
}
|
2013-05-08 16:42:46 +00:00
|
|
|
Dart_Handle library_url = Dart_LibraryUrl(library);
|
|
|
|
const char* library_url_string = NULL;
|
|
|
|
result = Dart_StringToCString(library_url, &library_url_string);
|
|
|
|
if (Dart_IsError(result)) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2012-09-04 20:46:30 +00:00
|
|
|
bool is_dart_scheme_url = DartUtils::IsDartSchemeURL(url_string);
|
2013-05-08 16:42:46 +00:00
|
|
|
bool is_io_library = DartUtils::IsDartIOLibURL(library_url_string);
|
|
|
|
|
|
|
|
// Handle URI canonicalization requests.
|
2013-05-31 16:36:27 +00:00
|
|
|
if (tag == Dart_kCanonicalizeUrl) {
|
2013-05-08 16:42:46 +00:00
|
|
|
// If this is a Dart Scheme URL or 'part' of a io library
|
|
|
|
// then it is not modified as it will be handled internally.
|
|
|
|
if (is_dart_scheme_url || is_io_library) {
|
2012-09-04 20:46:30 +00:00
|
|
|
return url;
|
|
|
|
}
|
|
|
|
// Resolve the url within the context of the library's URL.
|
2012-09-05 18:49:07 +00:00
|
|
|
Dart_Handle builtin_lib =
|
|
|
|
Builtin::LoadAndCheckLibrary(Builtin::kBuiltinLibrary);
|
2012-12-04 20:27:00 +00:00
|
|
|
return ResolveUri(library_url, url, builtin_lib);
|
2012-09-04 20:46:30 +00:00
|
|
|
}
|
2013-05-08 16:42:46 +00:00
|
|
|
|
|
|
|
// Handle 'import' of dart scheme URIs (i.e they start with 'dart:').
|
2012-09-04 20:46:30 +00:00
|
|
|
if (is_dart_scheme_url) {
|
2013-05-31 16:36:27 +00:00
|
|
|
if (tag == Dart_kImportTag) {
|
2013-01-24 21:56:10 +00:00
|
|
|
// Handle imports of other built-in libraries present in the SDK.
|
2013-02-22 01:24:57 +00:00
|
|
|
if (DartUtils::IsDartIOLibURL(url_string)) {
|
2014-05-07 21:46:05 +00:00
|
|
|
return Builtin::LoadLibrary(url, Builtin::kIOLibrary);
|
2013-01-24 21:56:10 +00:00
|
|
|
}
|
2013-10-17 17:49:45 +00:00
|
|
|
return NewError("The built-in library '%s' is not available"
|
|
|
|
" on the stand-alone VM.\n", url_string);
|
2012-09-04 20:46:30 +00:00
|
|
|
} else {
|
2013-05-31 16:36:27 +00:00
|
|
|
ASSERT(tag == Dart_kSourceTag);
|
2013-10-17 17:49:45 +00:00
|
|
|
return NewError("Unable to load source '%s' ", url_string);
|
2012-09-04 20:46:30 +00:00
|
|
|
}
|
2013-05-08 16:42:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Handle 'part' of IO library.
|
|
|
|
if (is_io_library) {
|
2013-05-31 16:36:27 +00:00
|
|
|
if (tag == Dart_kSourceTag) {
|
2014-03-18 11:29:06 +00:00
|
|
|
// Prepend the library URI to form a unique script URI for the part.
|
|
|
|
intptr_t len = snprintf(NULL, 0, "%s/%s", library_url_string, url_string);
|
|
|
|
char* part_uri = reinterpret_cast<char*>(malloc(len + 1));
|
|
|
|
snprintf(part_uri, len + 1, "%s/%s", library_url_string, url_string);
|
|
|
|
Dart_Handle part_uri_obj = DartUtils::NewString(part_uri);
|
|
|
|
free(part_uri);
|
2013-05-08 16:42:46 +00:00
|
|
|
return Dart_LoadSource(
|
2014-03-18 11:29:06 +00:00
|
|
|
library,
|
|
|
|
part_uri_obj,
|
2014-07-31 21:25:23 +00:00
|
|
|
Builtin::PartSource(Builtin::kIOLibrary, url_string), 0, 0);
|
2013-05-08 16:42:46 +00:00
|
|
|
} else {
|
2013-05-31 16:36:27 +00:00
|
|
|
ASSERT(tag == Dart_kImportTag);
|
2013-10-17 17:49:45 +00:00
|
|
|
return NewError("Unable to import '%s' ", url_string);
|
2012-09-04 20:46:30 +00:00
|
|
|
}
|
|
|
|
}
|
2013-05-08 16:42:46 +00:00
|
|
|
|
|
|
|
Dart_Handle builtin_lib =
|
|
|
|
Builtin::LoadAndCheckLibrary(Builtin::kBuiltinLibrary);
|
2014-03-03 14:51:44 +00:00
|
|
|
if (DartUtils::IsDartExtensionSchemeURL(url_string)) {
|
2014-03-04 14:39:12 +00:00
|
|
|
// Load a native code shared library to use in a native extension
|
2013-05-31 16:36:27 +00:00
|
|
|
if (tag != Dart_kImportTag) {
|
2013-10-17 17:49:45 +00:00
|
|
|
return NewError("Dart extensions must use import: '%s'", url_string);
|
2012-09-04 20:46:30 +00:00
|
|
|
}
|
2014-03-04 14:39:12 +00:00
|
|
|
Dart_Handle path_parts = DartUtils::ExtensionPathFromUri(url, builtin_lib);
|
|
|
|
if (Dart_IsError(path_parts)) {
|
|
|
|
return path_parts;
|
|
|
|
}
|
|
|
|
const char* extension_directory = NULL;
|
|
|
|
Dart_StringToCString(Dart_ListGetAt(path_parts, 0), &extension_directory);
|
|
|
|
const char* extension_filename = NULL;
|
|
|
|
Dart_StringToCString(Dart_ListGetAt(path_parts, 1), &extension_filename);
|
|
|
|
const char* extension_name = NULL;
|
|
|
|
Dart_StringToCString(Dart_ListGetAt(path_parts, 2), &extension_name);
|
|
|
|
|
|
|
|
return Extensions::LoadExtension(extension_directory,
|
|
|
|
extension_filename,
|
|
|
|
extension_name,
|
|
|
|
library);
|
2012-09-04 20:46:30 +00:00
|
|
|
}
|
2014-09-04 06:42:01 +00:00
|
|
|
|
|
|
|
// Handle 'import' or 'part' requests for all other URIs. Call dart code to
|
|
|
|
// read the source code asynchronously.
|
|
|
|
return LoadDataAsync_Invoke(Dart_NewInteger(tag),
|
|
|
|
url,
|
|
|
|
library_url,
|
|
|
|
builtin_lib);
|
2012-09-04 20:46:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-03-21 18:47:49 +00:00
|
|
|
const uint8_t* DartUtils::SniffForMagicNumber(const uint8_t* text_buffer,
|
2013-03-21 19:49:50 +00:00
|
|
|
intptr_t* buffer_len,
|
2013-03-21 18:47:49 +00:00
|
|
|
bool* is_snapshot) {
|
|
|
|
intptr_t len = sizeof(magic_number);
|
|
|
|
for (intptr_t i = 0; i < len; i++) {
|
|
|
|
if (text_buffer[i] != magic_number[i]) {
|
|
|
|
*is_snapshot = false;
|
|
|
|
return text_buffer;
|
|
|
|
}
|
2012-09-04 20:46:30 +00:00
|
|
|
}
|
2013-03-21 18:47:49 +00:00
|
|
|
*is_snapshot = true;
|
2013-03-21 19:49:50 +00:00
|
|
|
ASSERT(*buffer_len > len);
|
|
|
|
*buffer_len -= len;
|
2013-03-21 18:47:49 +00:00
|
|
|
return text_buffer + len;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DartUtils::WriteMagicNumber(File* file) {
|
|
|
|
// Write a magic number and version information into the snapshot file.
|
|
|
|
bool bytes_written = file->WriteFully(magic_number, sizeof(magic_number));
|
|
|
|
ASSERT(bytes_written);
|
2012-09-04 20:46:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Dart_Handle DartUtils::LoadScript(const char* script_uri,
|
|
|
|
Dart_Handle builtin_lib) {
|
2014-09-04 06:42:01 +00:00
|
|
|
Dart_Handle uri = Dart_NewStringFromCString(script_uri);
|
|
|
|
return LoadDataAsync_Invoke(Dart_Null(), uri, Dart_Null(), builtin_lib);
|
2014-05-23 17:43:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Callback function, gets called from asynchronous script and library
|
|
|
|
// reading code when there is an i/o error.
|
|
|
|
void FUNCTION_NAME(Builtin_AsyncLoadError)(Dart_NativeArguments args) {
|
2014-07-31 21:09:33 +00:00
|
|
|
// Dart_Handle source_uri = Dart_GetNativeArgument(args, 0);
|
|
|
|
Dart_Handle library_uri = Dart_GetNativeArgument(args, 1);
|
|
|
|
Dart_Handle error = Dart_GetNativeArgument(args, 2);
|
|
|
|
|
|
|
|
Dart_Handle library = Dart_LookupLibrary(library_uri);
|
|
|
|
// If a library with the given uri exists, give it a chance to handle
|
|
|
|
// the error. If the load requests stems from a deferred library load,
|
|
|
|
// an IO error is not fatal.
|
|
|
|
if (!Dart_IsError(library)) {
|
|
|
|
ASSERT(Dart_IsLibrary(library));
|
|
|
|
Dart_Handle res = Dart_LibraryHandleError(library, error);
|
|
|
|
if (Dart_IsNull(res)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// The error was not handled above. Propagate an unhandled exception.
|
|
|
|
error = Dart_NewUnhandledExceptionError(error);
|
|
|
|
Dart_PropagateError(error);
|
2014-05-23 17:43:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Callback function that gets called from dartutils when the library
|
|
|
|
// source has been read. Loads the library or part into the VM.
|
2014-09-04 06:42:01 +00:00
|
|
|
void FUNCTION_NAME(Builtin_LoadScript)(Dart_NativeArguments args) {
|
2014-05-23 17:43:14 +00:00
|
|
|
Dart_Handle tag_in = Dart_GetNativeArgument(args, 0);
|
|
|
|
Dart_Handle resolved_script_uri = Dart_GetNativeArgument(args, 1);
|
|
|
|
Dart_Handle library_uri = Dart_GetNativeArgument(args, 2);
|
2014-09-04 06:42:01 +00:00
|
|
|
Dart_Handle source_data = Dart_GetNativeArgument(args, 3);
|
|
|
|
|
|
|
|
Dart_TypedData_Type type = Dart_GetTypeOfExternalTypedData(source_data);
|
|
|
|
bool external = type == Dart_TypedData_kUint8;
|
|
|
|
uint8_t* data = NULL;
|
|
|
|
intptr_t num_bytes;
|
|
|
|
Dart_Handle result = Dart_TypedDataAcquireData(
|
|
|
|
source_data, &type, reinterpret_cast<void**>(&data), &num_bytes);
|
|
|
|
if (Dart_IsError(result)) Dart_PropagateError(result);
|
|
|
|
|
|
|
|
uint8_t* buffer_copy = NULL;
|
|
|
|
if (!external) {
|
|
|
|
// If the buffer is not external, take a copy.
|
|
|
|
buffer_copy = reinterpret_cast<uint8_t*>(malloc(num_bytes));
|
|
|
|
memmove(buffer_copy, data, num_bytes);
|
|
|
|
data = buffer_copy;
|
|
|
|
}
|
2014-05-23 17:43:14 +00:00
|
|
|
|
2014-09-04 06:42:01 +00:00
|
|
|
Dart_TypedDataReleaseData(source_data);
|
2014-05-23 17:43:14 +00:00
|
|
|
|
2014-09-04 06:42:01 +00:00
|
|
|
if (Dart_IsNull(tag_in) && Dart_IsNull(library_uri)) {
|
|
|
|
// Entry file. Check for payload and load accordingly.
|
|
|
|
bool is_snapshot = false;
|
|
|
|
const uint8_t *payload =
|
|
|
|
DartUtils::SniffForMagicNumber(data, &num_bytes, &is_snapshot);
|
|
|
|
|
|
|
|
if (is_snapshot) {
|
|
|
|
result = Dart_LoadScriptFromSnapshot(payload, num_bytes);
|
|
|
|
} else {
|
|
|
|
Dart_Handle source = Dart_NewStringFromUTF8(data, num_bytes);
|
|
|
|
if (Dart_IsError(source)) {
|
|
|
|
result = DartUtils::NewError("%s is not a valid UTF-8 script",
|
|
|
|
resolved_script_uri);
|
|
|
|
} else {
|
|
|
|
result = Dart_LoadScript(resolved_script_uri, source, 0, 0);
|
|
|
|
}
|
|
|
|
}
|
2014-05-23 17:43:14 +00:00
|
|
|
} else {
|
2014-09-04 06:42:01 +00:00
|
|
|
int64_t tag = DartUtils::GetIntegerValue(tag_in);
|
|
|
|
|
|
|
|
Dart_Handle source = Dart_NewStringFromUTF8(data, num_bytes);
|
|
|
|
if (Dart_IsError(source)) {
|
|
|
|
result = DartUtils::NewError("%s is not a valid UTF-8 script",
|
|
|
|
resolved_script_uri);
|
|
|
|
} else {
|
|
|
|
if (tag == Dart_kImportTag) {
|
|
|
|
result = Dart_LoadLibrary(resolved_script_uri, source, 0, 0);
|
|
|
|
} else {
|
|
|
|
ASSERT(tag == Dart_kSourceTag);
|
|
|
|
Dart_Handle library = Dart_LookupLibrary(library_uri);
|
|
|
|
DART_CHECK_VALID(library);
|
|
|
|
result = Dart_LoadSource(library, resolved_script_uri, source, 0, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (buffer_copy != NULL) {
|
|
|
|
free(const_cast<uint8_t *>(buffer_copy));
|
2014-05-23 17:43:14 +00:00
|
|
|
}
|
2014-09-04 06:42:01 +00:00
|
|
|
|
2014-07-31 21:09:33 +00:00
|
|
|
if (Dart_IsError(result)) {
|
|
|
|
Dart_PropagateError(result);
|
|
|
|
}
|
2014-05-23 17:43:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-06-13 22:43:31 +00:00
|
|
|
// Callback function that gets called from dartutils when there are
|
2014-06-17 21:05:30 +00:00
|
|
|
// no more outstanding load requests.
|
2014-06-13 22:43:31 +00:00
|
|
|
void FUNCTION_NAME(Builtin_DoneLoading)(Dart_NativeArguments args) {
|
2014-07-22 16:56:14 +00:00
|
|
|
Dart_Handle res = Dart_FinalizeLoading(true);
|
2014-06-13 22:43:31 +00:00
|
|
|
if (Dart_IsError(res)) {
|
2014-07-31 21:09:33 +00:00
|
|
|
// TODO(hausner): If compilation/loading errors are supposed to
|
|
|
|
// be observable by the program, we need to mark the bad library
|
|
|
|
// with the error instead of propagating it.
|
2014-06-13 22:43:31 +00:00
|
|
|
Dart_PropagateError(res);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-04 20:46:30 +00:00
|
|
|
Dart_Handle DartUtils::PrepareForScriptLoading(const char* package_root,
|
|
|
|
Dart_Handle builtin_lib) {
|
2014-07-23 20:31:23 +00:00
|
|
|
// First ensure all required libraries are available.
|
|
|
|
Dart_Handle url = NewString(kAsyncLibURL);
|
2012-09-08 01:00:28 +00:00
|
|
|
DART_CHECK_VALID(url);
|
2013-01-07 11:23:16 +00:00
|
|
|
Dart_Handle async_lib = Dart_LookupLibrary(url);
|
|
|
|
DART_CHECK_VALID(async_lib);
|
2012-09-05 18:49:07 +00:00
|
|
|
Dart_Handle io_lib = Builtin::LoadAndCheckLibrary(Builtin::kIOLibrary);
|
2014-07-22 20:08:15 +00:00
|
|
|
|
|
|
|
// We need to ensure that all the scripts loaded so far are finalized
|
|
|
|
// as we are about to invoke some Dart code below to setup closures.
|
2014-07-23 20:31:23 +00:00
|
|
|
Dart_Handle result = Dart_FinalizeLoading(false);
|
2014-07-22 20:08:15 +00:00
|
|
|
DART_CHECK_VALID(result);
|
|
|
|
|
2014-07-23 20:31:23 +00:00
|
|
|
// Setup the internal library's 'internalPrint' function.
|
|
|
|
Dart_Handle print = Dart_Invoke(
|
|
|
|
builtin_lib, NewString("_getPrintClosure"), 0, NULL);
|
|
|
|
url = NewString(kInternalLibURL);
|
|
|
|
DART_CHECK_VALID(url);
|
|
|
|
Dart_Handle internal_lib = Dart_LookupLibrary(url);
|
|
|
|
DART_CHECK_VALID(internal_lib);
|
|
|
|
result = Dart_SetField(internal_lib,
|
|
|
|
NewString("_printClosure"),
|
|
|
|
print);
|
|
|
|
DART_CHECK_VALID(result);
|
|
|
|
|
|
|
|
// Setup the 'timer' factory.
|
2012-09-08 01:00:28 +00:00
|
|
|
Dart_Handle timer_closure =
|
2012-10-31 17:56:46 +00:00
|
|
|
Dart_Invoke(io_lib, NewString("_getTimerFactoryClosure"), 0, NULL);
|
2012-09-08 01:00:28 +00:00
|
|
|
Dart_Handle args[1];
|
|
|
|
args[0] = timer_closure;
|
2012-10-31 17:56:46 +00:00
|
|
|
DART_CHECK_VALID(Dart_Invoke(
|
2013-01-07 11:23:16 +00:00
|
|
|
async_lib, NewString("_setTimerFactoryClosure"), 1, args));
|
2012-09-04 20:46:30 +00:00
|
|
|
|
2013-12-02 16:27:07 +00:00
|
|
|
// Setup the 'scheduleImmediate' closure.
|
|
|
|
url = NewString(kIsolateLibURL);
|
|
|
|
DART_CHECK_VALID(url);
|
|
|
|
Dart_Handle isolate_lib = Dart_LookupLibrary(url);
|
|
|
|
DART_CHECK_VALID(isolate_lib);
|
|
|
|
Dart_Handle schedule_immediate_closure =
|
|
|
|
Dart_Invoke(isolate_lib, NewString("_getIsolateScheduleImmediateClosure"),
|
|
|
|
0, NULL);
|
|
|
|
args[0] = schedule_immediate_closure;
|
|
|
|
DART_CHECK_VALID(Dart_Invoke(
|
|
|
|
async_lib, NewString("_setScheduleImmediateClosure"), 1, args));
|
|
|
|
|
2013-09-25 13:52:15 +00:00
|
|
|
// Setup the corelib 'Uri.base' getter.
|
2013-12-02 16:27:07 +00:00
|
|
|
url = NewString(kCoreLibURL);
|
|
|
|
DART_CHECK_VALID(url);
|
|
|
|
Dart_Handle corelib = Dart_LookupLibrary(url);
|
2013-10-15 16:02:07 +00:00
|
|
|
DART_CHECK_VALID(corelib);
|
2013-09-25 13:52:15 +00:00
|
|
|
Dart_Handle uri_base = Dart_Invoke(
|
|
|
|
builtin_lib, NewString("_getUriBaseClosure"), 0, NULL);
|
|
|
|
DART_CHECK_VALID(uri_base);
|
|
|
|
result = Dart_SetField(corelib,
|
|
|
|
NewString("_uriBaseClosure"),
|
|
|
|
uri_base);
|
|
|
|
DART_CHECK_VALID(result);
|
2013-06-19 00:02:38 +00:00
|
|
|
|
|
|
|
if (IsWindowsHost()) {
|
|
|
|
// Set running on Windows flag.
|
|
|
|
result = Dart_Invoke(builtin_lib, NewString("_setWindows"), 0, NULL);
|
|
|
|
if (Dart_IsError(result)) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set current working directory.
|
|
|
|
result = SetWorkingDirectory(builtin_lib);
|
|
|
|
if (Dart_IsError(result)) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2012-09-04 20:46:30 +00:00
|
|
|
// Set up package root if specified.
|
|
|
|
if (package_root != NULL) {
|
2013-10-29 11:33:34 +00:00
|
|
|
result = NewString(package_root);
|
|
|
|
if (!Dart_IsError(result)) {
|
|
|
|
const int kNumArgs = 1;
|
|
|
|
Dart_Handle dart_args[kNumArgs];
|
|
|
|
dart_args[0] = result;
|
|
|
|
return Dart_Invoke(builtin_lib,
|
2012-10-31 17:56:46 +00:00
|
|
|
NewString("_setPackageRoot"),
|
2012-09-04 20:46:30 +00:00
|
|
|
kNumArgs,
|
|
|
|
dart_args);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-02-06 15:42:15 +00:00
|
|
|
bool DartUtils::PostNull(Dart_Port port_id) {
|
|
|
|
// Post a message with just the null object.
|
2012-02-21 08:59:41 +00:00
|
|
|
return Dart_PostCObject(port_id, CObject::Null()->AsApiCObject());
|
2012-02-06 15:42:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool DartUtils::PostInt32(Dart_Port port_id, int32_t value) {
|
|
|
|
// Post a message with the integer value.
|
|
|
|
int32_t min = 0xc0000000; // -1073741824
|
|
|
|
int32_t max = 0x3fffffff; // 1073741823
|
|
|
|
ASSERT(min <= value && value < max);
|
|
|
|
Dart_CObject object;
|
2013-05-31 16:36:27 +00:00
|
|
|
object.type = Dart_CObject_kInt32;
|
2012-02-06 15:42:15 +00:00
|
|
|
object.value.as_int32 = value;
|
|
|
|
return Dart_PostCObject(port_id, &object);
|
|
|
|
}
|
2012-02-21 08:59:41 +00:00
|
|
|
|
|
|
|
|
2014-02-19 09:44:26 +00:00
|
|
|
bool DartUtils::PostInt64(Dart_Port port_id, int64_t value) {
|
|
|
|
// Post a message with the integer value.
|
|
|
|
Dart_CObject object;
|
|
|
|
object.type = Dart_CObject_kInt64;
|
|
|
|
object.value.as_int64 = value;
|
|
|
|
return Dart_PostCObject(port_id, &object);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-06-20 18:11:47 +00:00
|
|
|
Dart_Handle DartUtils::GetDartType(const char* library_url,
|
|
|
|
const char* class_name) {
|
|
|
|
return Dart_GetType(Dart_LookupLibrary(NewString(library_url)),
|
|
|
|
NewString(class_name), 0, NULL);
|
2012-11-14 13:38:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-03-13 13:00:47 +00:00
|
|
|
Dart_Handle DartUtils::NewDartOSError() {
|
|
|
|
// Extract the current OS error.
|
|
|
|
OSError os_error;
|
|
|
|
return NewDartOSError(&os_error);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Dart_Handle DartUtils::NewDartOSError(OSError* os_error) {
|
2012-11-14 13:38:32 +00:00
|
|
|
// Create a dart:io OSError object with the information retrieved from the OS.
|
2013-06-20 18:11:47 +00:00
|
|
|
Dart_Handle type = GetDartType(kIOLibURL, "OSError");
|
2013-07-15 10:32:37 +00:00
|
|
|
ASSERT(!Dart_IsError(type));
|
2012-03-13 13:00:47 +00:00
|
|
|
Dart_Handle args[2];
|
2012-10-31 17:56:46 +00:00
|
|
|
args[0] = NewString(os_error->message());
|
2012-03-13 13:00:47 +00:00
|
|
|
args[1] = Dart_NewInteger(os_error->code());
|
2013-06-20 18:11:47 +00:00
|
|
|
return Dart_New(type, Dart_Null(), 2, args);
|
2012-11-14 13:38:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-06-25 13:54:42 +00:00
|
|
|
Dart_Handle DartUtils::NewDartExceptionWithOSError(const char* library_url,
|
|
|
|
const char* exception_name,
|
|
|
|
const char* message,
|
|
|
|
Dart_Handle os_error) {
|
|
|
|
// Create a Dart Exception object with a message and an OSError.
|
|
|
|
Dart_Handle type = GetDartType(library_url, exception_name);
|
2013-07-15 10:32:37 +00:00
|
|
|
ASSERT(!Dart_IsError(type));
|
2012-11-14 13:38:32 +00:00
|
|
|
Dart_Handle args[2];
|
|
|
|
args[0] = NewString(message);
|
|
|
|
args[1] = os_error;
|
2013-06-20 18:11:47 +00:00
|
|
|
return Dart_New(type, Dart_Null(), 2, args);
|
2012-11-14 13:38:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Dart_Handle DartUtils::NewDartExceptionWithMessage(const char* library_url,
|
|
|
|
const char* exception_name,
|
|
|
|
const char* message) {
|
|
|
|
// Create a Dart Exception object with a message.
|
2013-06-20 18:11:47 +00:00
|
|
|
Dart_Handle type = GetDartType(library_url, exception_name);
|
2013-07-15 10:32:37 +00:00
|
|
|
ASSERT(!Dart_IsError(type));
|
2013-04-29 12:43:53 +00:00
|
|
|
if (message != NULL) {
|
|
|
|
Dart_Handle args[1];
|
|
|
|
args[0] = NewString(message);
|
2013-06-20 18:11:47 +00:00
|
|
|
return Dart_New(type, Dart_Null(), 1, args);
|
2013-04-29 12:43:53 +00:00
|
|
|
} else {
|
2013-06-20 18:11:47 +00:00
|
|
|
return Dart_New(type, Dart_Null(), 0, NULL);
|
2013-04-29 12:43:53 +00:00
|
|
|
}
|
2012-11-14 13:38:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Dart_Handle DartUtils::NewDartArgumentError(const char* message) {
|
|
|
|
return NewDartExceptionWithMessage(kCoreLibURL,
|
|
|
|
"ArgumentError",
|
|
|
|
message);
|
2012-03-13 13:00:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-06-25 13:54:42 +00:00
|
|
|
Dart_Handle DartUtils::NewDartIOException(const char* exception_name,
|
|
|
|
const char* message,
|
|
|
|
Dart_Handle os_error) {
|
|
|
|
// Create a dart:io exception object of the given type.
|
|
|
|
return NewDartExceptionWithOSError(kIOLibURL,
|
|
|
|
exception_name,
|
|
|
|
message,
|
|
|
|
os_error);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-10-17 17:49:45 +00:00
|
|
|
Dart_Handle DartUtils::NewError(const char* format, ...) {
|
|
|
|
va_list args;
|
|
|
|
va_start(args, format);
|
|
|
|
intptr_t len = vsnprintf(NULL, 0, format, args);
|
|
|
|
va_end(args);
|
|
|
|
|
|
|
|
char* buffer = reinterpret_cast<char*>(Dart_ScopeAllocate(len + 1));
|
|
|
|
va_list args2;
|
|
|
|
va_start(args2, format);
|
|
|
|
vsnprintf(buffer, (len + 1), format, args2);
|
|
|
|
va_end(args2);
|
|
|
|
|
|
|
|
return Dart_NewApiError(buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-03-06 11:38:41 +00:00
|
|
|
Dart_Handle DartUtils::NewInternalError(const char* message) {
|
2013-07-15 10:32:37 +00:00
|
|
|
return NewDartExceptionWithMessage(kCoreLibURL, "_InternalError", message);
|
2013-03-06 11:38:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-09-13 16:40:36 +00:00
|
|
|
bool DartUtils::SetOriginalWorkingDirectory() {
|
2012-09-04 20:46:30 +00:00
|
|
|
original_working_directory = Directory::Current();
|
2013-09-13 16:40:36 +00:00
|
|
|
return original_working_directory != NULL;
|
2012-09-04 20:46:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-02-21 08:59:41 +00:00
|
|
|
// Statically allocated Dart_CObject instances for immutable
|
|
|
|
// objects. As these will be used by different threads the use of
|
|
|
|
// these depends on the fact that the marking internally in the
|
|
|
|
// Dart_CObject structure is not marking simple value objects.
|
2013-05-31 16:36:27 +00:00
|
|
|
Dart_CObject CObject::api_null_ = { Dart_CObject_kNull , { 0 } };
|
|
|
|
Dart_CObject CObject::api_true_ = { Dart_CObject_kBool , { true } };
|
|
|
|
Dart_CObject CObject::api_false_ = { Dart_CObject_kBool, { false } };
|
2012-02-21 08:59:41 +00:00
|
|
|
CObject CObject::null_ = CObject(&api_null_);
|
|
|
|
CObject CObject::true_ = CObject(&api_true_);
|
|
|
|
CObject CObject::false_ = CObject(&api_false_);
|
|
|
|
|
|
|
|
|
|
|
|
CObject* CObject::Null() {
|
|
|
|
return &null_;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CObject* CObject::True() {
|
|
|
|
return &true_;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CObject* CObject::False() {
|
|
|
|
return &false_;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CObject* CObject::Bool(bool value) {
|
|
|
|
return value ? &true_ : &false_;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-05-31 16:36:27 +00:00
|
|
|
Dart_CObject* CObject::New(Dart_CObject_Type type, int additional_bytes) {
|
2012-02-21 08:59:41 +00:00
|
|
|
Dart_CObject* cobject = reinterpret_cast<Dart_CObject*>(
|
|
|
|
Dart_ScopeAllocate(sizeof(Dart_CObject) + additional_bytes));
|
|
|
|
cobject->type = type;
|
|
|
|
return cobject;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Dart_CObject* CObject::NewInt32(int32_t value) {
|
2013-05-31 16:36:27 +00:00
|
|
|
Dart_CObject* cobject = New(Dart_CObject_kInt32);
|
2012-02-21 08:59:41 +00:00
|
|
|
cobject->value.as_int32 = value;
|
|
|
|
return cobject;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Dart_CObject* CObject::NewInt64(int64_t value) {
|
2013-05-31 16:36:27 +00:00
|
|
|
Dart_CObject* cobject = New(Dart_CObject_kInt64);
|
2012-02-21 08:59:41 +00:00
|
|
|
cobject->value.as_int64 = value;
|
|
|
|
return cobject;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-02-23 11:11:48 +00:00
|
|
|
Dart_CObject* CObject::NewIntptr(intptr_t value) {
|
|
|
|
// Pointer values passed as intptr_t are always send as int64_t.
|
2013-05-31 16:36:27 +00:00
|
|
|
Dart_CObject* cobject = New(Dart_CObject_kInt64);
|
2012-02-23 11:11:48 +00:00
|
|
|
cobject->value.as_int64 = value;
|
|
|
|
return cobject;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-09-09 21:47:44 +00:00
|
|
|
static bool IsHexDigit(char c) {
|
|
|
|
return (('0' <= c) && (c <= '9'))
|
|
|
|
|| (('A' <= c) && (c <= 'F'))
|
|
|
|
|| (('a' <= c) && (c <= 'f'));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int HexDigitToInt(char c) {
|
|
|
|
if (('0' <= c) && (c <= '9')) return c - '0';
|
|
|
|
if (('A' <= c) && (c <= 'F')) return 10 + (c - 'A');
|
|
|
|
return 10 + (c - 'a');
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Dart_CObject* CObject::NewBigint(const char* hex_value) {
|
|
|
|
if (hex_value == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
bool neg = false;
|
|
|
|
if (hex_value[0] == '-') {
|
|
|
|
neg = true;
|
|
|
|
hex_value++;
|
|
|
|
}
|
|
|
|
if ((hex_value[0] != '0') ||
|
|
|
|
((hex_value[1] != 'x') && (hex_value[1] != 'X'))) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
hex_value += 2;
|
|
|
|
intptr_t hex_i = strlen(hex_value); // Terminating byte excluded.
|
|
|
|
if (hex_i == 0) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
const int kBitsPerHexDigit = 4;
|
|
|
|
const int kHexDigitsPerDigit = 8;
|
|
|
|
const int kBitsPerDigit = kBitsPerHexDigit * kHexDigitsPerDigit;
|
|
|
|
const intptr_t len = (hex_i + kHexDigitsPerDigit - 1) / kHexDigitsPerDigit;
|
|
|
|
Dart_CObject* cobject = New(Dart_CObject_kBigint);
|
|
|
|
cobject->value.as_bigint.digits = NewUint32Array(len);
|
|
|
|
uint32_t* digits = reinterpret_cast<uint32_t*>(
|
|
|
|
cobject->value.as_bigint.digits->value.as_typed_data.values);
|
|
|
|
intptr_t used = 0;
|
|
|
|
uint32_t digit = 0;
|
|
|
|
intptr_t bit_i = 0;
|
|
|
|
while (--hex_i >= 0) {
|
|
|
|
if (!IsHexDigit(hex_value[hex_i])) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
digit += HexDigitToInt(hex_value[hex_i]) << bit_i;
|
|
|
|
bit_i += kBitsPerHexDigit;
|
|
|
|
if (bit_i == kBitsPerDigit) {
|
|
|
|
bit_i = 0;
|
|
|
|
digits[used++] = digit;
|
|
|
|
digit = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (bit_i != 0) {
|
|
|
|
digits[used++] = digit;
|
|
|
|
}
|
|
|
|
while ((used > 0) && (digits[used - 1] == 0)) {
|
|
|
|
used--;
|
|
|
|
}
|
|
|
|
cobject->value.as_bigint.used = used;
|
|
|
|
if (used == 0) {
|
|
|
|
neg = false;
|
|
|
|
}
|
|
|
|
cobject->value.as_bigint.neg = neg;
|
|
|
|
return cobject;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static char IntToHexDigit(int i) {
|
|
|
|
ASSERT(0 <= i && i < 16);
|
|
|
|
if (i < 10) return static_cast<char>('0' + i);
|
|
|
|
return static_cast<char>('A' + (i - 10));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
char* CObject::BigintToHexValue(Dart_CObject* bigint) {
|
|
|
|
ASSERT(bigint->type == Dart_CObject_kBigint);
|
|
|
|
const intptr_t used = bigint->value.as_bigint.used;
|
|
|
|
if (used == 0) {
|
|
|
|
const char* zero = "0x0";
|
|
|
|
const size_t len = strlen(zero) + 1;
|
|
|
|
char* hex_value = reinterpret_cast<char*>(malloc(len));
|
|
|
|
strncpy(hex_value, zero, len);
|
|
|
|
return hex_value;
|
|
|
|
}
|
|
|
|
const int kBitsPerHexDigit = 4;
|
|
|
|
const int kHexDigitsPerDigit = 8;
|
|
|
|
const intptr_t kMaxUsed = (kIntptrMax - 4) / kHexDigitsPerDigit;
|
|
|
|
if (used > kMaxUsed) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
intptr_t hex_len = (used - 1) * kHexDigitsPerDigit;
|
|
|
|
const uint32_t* digits = reinterpret_cast<uint32_t*>(
|
|
|
|
bigint->value.as_bigint.digits->value.as_typed_data.values);
|
|
|
|
// The most significant digit may use fewer than kHexDigitsPerDigit digits.
|
|
|
|
uint32_t digit = digits[used - 1];
|
|
|
|
ASSERT(digit != 0); // Value must be clamped.
|
|
|
|
while (digit != 0) {
|
|
|
|
hex_len++;
|
|
|
|
digit >>= kBitsPerHexDigit;
|
|
|
|
}
|
|
|
|
const bool neg = bigint->value.as_bigint.neg;
|
|
|
|
// Add bytes for '0x', for the minus sign, and for the trailing \0 character.
|
|
|
|
const int32_t len = (neg ? 1 : 0) + 2 + hex_len + 1;
|
|
|
|
char* hex_value = reinterpret_cast<char*>(malloc(len));
|
|
|
|
intptr_t pos = len;
|
|
|
|
hex_value[--pos] = '\0';
|
|
|
|
for (intptr_t i = 0; i < (used - 1); i++) {
|
|
|
|
digit = digits[i];
|
|
|
|
for (intptr_t j = 0; j < kHexDigitsPerDigit; j++) {
|
|
|
|
hex_value[--pos] = IntToHexDigit(digit & 0xf);
|
|
|
|
digit >>= kBitsPerHexDigit;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
digit = digits[used - 1];
|
|
|
|
while (digit != 0) {
|
|
|
|
hex_value[--pos] = IntToHexDigit(digit & 0xf);
|
|
|
|
digit >>= kBitsPerHexDigit;
|
|
|
|
}
|
|
|
|
hex_value[--pos] = 'x';
|
|
|
|
hex_value[--pos] = '0';
|
|
|
|
if (neg) {
|
|
|
|
hex_value[--pos] = '-';
|
|
|
|
}
|
|
|
|
ASSERT(pos == 0);
|
|
|
|
return hex_value;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-02-21 08:59:41 +00:00
|
|
|
Dart_CObject* CObject::NewDouble(double value) {
|
2013-05-31 16:36:27 +00:00
|
|
|
Dart_CObject* cobject = New(Dart_CObject_kDouble);
|
2012-02-21 08:59:41 +00:00
|
|
|
cobject->value.as_double = value;
|
|
|
|
return cobject;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-09-11 16:56:12 +00:00
|
|
|
Dart_CObject* CObject::NewString(intptr_t length) {
|
2013-05-31 16:36:27 +00:00
|
|
|
Dart_CObject* cobject = New(Dart_CObject_kString, length + 1);
|
2012-02-21 08:59:41 +00:00
|
|
|
cobject->value.as_string = reinterpret_cast<char*>(cobject + 1);
|
|
|
|
return cobject;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Dart_CObject* CObject::NewString(const char* str) {
|
2013-10-07 20:19:37 +00:00
|
|
|
intptr_t length = strlen(str);
|
2012-02-21 08:59:41 +00:00
|
|
|
Dart_CObject* cobject = NewString(length);
|
|
|
|
memmove(cobject->value.as_string, str, length + 1);
|
|
|
|
return cobject;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-09-11 16:56:12 +00:00
|
|
|
Dart_CObject* CObject::NewArray(intptr_t length) {
|
2012-02-21 08:59:41 +00:00
|
|
|
Dart_CObject* cobject =
|
2013-05-31 16:36:27 +00:00
|
|
|
New(Dart_CObject_kArray, length * sizeof(Dart_CObject*)); // NOLINT
|
2012-02-21 08:59:41 +00:00
|
|
|
cobject->value.as_array.length = length;
|
|
|
|
cobject->value.as_array.values =
|
|
|
|
reinterpret_cast<Dart_CObject**>(cobject + 1);
|
|
|
|
return cobject;
|
|
|
|
}
|
2012-02-23 11:11:48 +00:00
|
|
|
|
|
|
|
|
2013-09-11 16:56:12 +00:00
|
|
|
Dart_CObject* CObject::NewUint8Array(intptr_t length) {
|
2013-05-31 16:36:27 +00:00
|
|
|
Dart_CObject* cobject = New(Dart_CObject_kTypedData, length);
|
|
|
|
cobject->value.as_typed_data.type = Dart_TypedData_kUint8;
|
2013-04-15 09:01:56 +00:00
|
|
|
cobject->value.as_typed_data.length = length;
|
|
|
|
cobject->value.as_typed_data.values = reinterpret_cast<uint8_t*>(cobject + 1);
|
2012-02-23 11:11:48 +00:00
|
|
|
return cobject;
|
|
|
|
}
|
2012-03-13 13:00:47 +00:00
|
|
|
|
|
|
|
|
2014-09-09 21:47:44 +00:00
|
|
|
Dart_CObject* CObject::NewUint32Array(intptr_t length) {
|
|
|
|
Dart_CObject* cobject = New(Dart_CObject_kTypedData, 4*length);
|
|
|
|
cobject->value.as_typed_data.type = Dart_TypedData_kUint32;
|
|
|
|
cobject->value.as_typed_data.length = length;
|
|
|
|
cobject->value.as_typed_data.values = reinterpret_cast<uint8_t*>(cobject + 1);
|
|
|
|
return cobject;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-01-31 18:53:21 +00:00
|
|
|
Dart_CObject* CObject::NewExternalUint8Array(
|
2013-09-11 16:56:12 +00:00
|
|
|
intptr_t length, uint8_t* data, void* peer,
|
2013-01-31 18:53:21 +00:00
|
|
|
Dart_WeakPersistentHandleFinalizer callback) {
|
2013-05-31 16:36:27 +00:00
|
|
|
Dart_CObject* cobject = New(Dart_CObject_kExternalTypedData);
|
|
|
|
cobject->value.as_external_typed_data.type = Dart_TypedData_kUint8;
|
2013-04-15 09:01:56 +00:00
|
|
|
cobject->value.as_external_typed_data.length = length;
|
|
|
|
cobject->value.as_external_typed_data.data = data;
|
|
|
|
cobject->value.as_external_typed_data.peer = peer;
|
|
|
|
cobject->value.as_external_typed_data.callback = callback;
|
2012-07-02 07:22:32 +00:00
|
|
|
return cobject;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-12-06 13:44:24 +00:00
|
|
|
Dart_CObject* CObject::NewIOBuffer(int64_t length) {
|
2013-09-11 16:56:12 +00:00
|
|
|
// Make sure that we do not have an integer overflow here. Actual check
|
|
|
|
// against max elements will be done at the time of writing, as the constant
|
|
|
|
// is not part of the public API.
|
2014-01-16 05:05:35 +00:00
|
|
|
if ((length < 0) || (length > kIntptrMax)) {
|
2013-09-11 16:56:12 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2014-01-16 05:05:35 +00:00
|
|
|
uint8_t* data = IOBuffer::Allocate(static_cast<intptr_t>(length));
|
2013-09-11 16:56:12 +00:00
|
|
|
ASSERT(data != NULL);
|
|
|
|
return NewExternalUint8Array(
|
|
|
|
static_cast<intptr_t>(length), data, data, IOBuffer::Finalizer);
|
2012-12-06 13:44:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CObject::FreeIOBufferData(Dart_CObject* cobject) {
|
2013-05-31 16:36:27 +00:00
|
|
|
ASSERT(cobject->type == Dart_CObject_kExternalTypedData);
|
2013-04-15 09:01:56 +00:00
|
|
|
cobject->value.as_external_typed_data.callback(
|
2014-03-04 18:11:19 +00:00
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
cobject->value.as_external_typed_data.peer);
|
2013-04-15 09:01:56 +00:00
|
|
|
cobject->value.as_external_typed_data.data = NULL;
|
2012-12-06 13:44:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-03-13 13:00:47 +00:00
|
|
|
CObject* CObject::IllegalArgumentError() {
|
|
|
|
CObjectArray* result = new CObjectArray(CObject::NewArray(1));
|
2012-09-25 12:27:52 +00:00
|
|
|
result->SetAt(0, new CObjectInt32(CObject::NewInt32(kArgumentError)));
|
2012-03-13 13:00:47 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-03-26 05:54:49 +00:00
|
|
|
CObject* CObject::FileClosedError() {
|
|
|
|
CObjectArray* result = new CObjectArray(CObject::NewArray(1));
|
|
|
|
result->SetAt(0, new CObjectInt32(CObject::NewInt32(kFileClosedError)));
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-03-13 13:00:47 +00:00
|
|
|
CObject* CObject::NewOSError() {
|
|
|
|
OSError os_error;
|
2012-03-19 11:26:41 +00:00
|
|
|
return NewOSError(&os_error);
|
|
|
|
}
|
|
|
|
|
|
|
|
CObject* CObject::NewOSError(OSError* os_error) {
|
2012-03-13 13:00:47 +00:00
|
|
|
CObject* error_message =
|
2012-03-19 11:26:41 +00:00
|
|
|
new CObjectString(CObject::NewString(os_error->message()));
|
2012-03-13 13:00:47 +00:00
|
|
|
CObjectArray* result = new CObjectArray(CObject::NewArray(3));
|
|
|
|
result->SetAt(0, new CObjectInt32(CObject::NewInt32(kOSError)));
|
2012-03-19 11:26:41 +00:00
|
|
|
result->SetAt(1, new CObjectInt32(CObject::NewInt32(os_error->code())));
|
2012-03-13 13:00:47 +00:00
|
|
|
result->SetAt(2, error_message);
|
|
|
|
return result;
|
|
|
|
}
|
2013-04-25 14:22:30 +00:00
|
|
|
|
|
|
|
} // namespace bin
|
|
|
|
} // namespace dart
|