2012-02-06 15:42:15 +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 "include/dart_api.h"
|
|
|
|
|
|
|
|
#include "vm/bigint_operations.h"
|
|
|
|
#include "vm/class_finalizer.h"
|
|
|
|
#include "vm/compiler.h"
|
|
|
|
#include "vm/dart.h"
|
|
|
|
#include "vm/dart_api_impl.h"
|
2012-02-18 10:10:28 +00:00
|
|
|
#include "vm/dart_api_message.h"
|
2011-10-05 05:20:07 +00:00
|
|
|
#include "vm/dart_api_state.h"
|
|
|
|
#include "vm/dart_entry.h"
|
|
|
|
#include "vm/debuginfo.h"
|
|
|
|
#include "vm/exceptions.h"
|
2012-05-01 09:20:40 +00:00
|
|
|
#include "vm/flags.h"
|
2011-10-05 05:20:07 +00:00
|
|
|
#include "vm/growable_array.h"
|
2012-02-01 18:53:40 +00:00
|
|
|
#include "vm/message.h"
|
2011-10-05 05:20:07 +00:00
|
|
|
#include "vm/native_entry.h"
|
2012-02-01 18:53:40 +00:00
|
|
|
#include "vm/native_message_handler.h"
|
2011-10-05 05:20:07 +00:00
|
|
|
#include "vm/object.h"
|
|
|
|
#include "vm/object_store.h"
|
|
|
|
#include "vm/port.h"
|
|
|
|
#include "vm/resolver.h"
|
|
|
|
#include "vm/stack_frame.h"
|
2012-07-24 00:01:50 +00:00
|
|
|
#include "vm/symbols.h"
|
2011-10-05 05:20:07 +00:00
|
|
|
#include "vm/timer.h"
|
2012-05-02 22:40:48 +00:00
|
|
|
#include "vm/unicode.h"
|
2011-10-05 05:20:07 +00:00
|
|
|
#include "vm/verifier.h"
|
2012-10-11 07:17:09 +00:00
|
|
|
#include "vm/version.h"
|
2011-10-05 05:20:07 +00:00
|
|
|
|
|
|
|
namespace dart {
|
|
|
|
|
2012-05-01 09:20:40 +00:00
|
|
|
DECLARE_FLAG(bool, print_class_table);
|
|
|
|
|
2012-02-09 08:47:19 +00:00
|
|
|
ThreadLocalKey Api::api_native_key_ = Thread::kUnsetThreadLocalKey;
|
|
|
|
|
2012-07-09 23:57:08 +00:00
|
|
|
|
2011-12-01 19:17:10 +00:00
|
|
|
const char* CanonicalFunction(const char* func) {
|
2011-11-10 19:48:55 +00:00
|
|
|
if (strncmp(func, "dart::", 6) == 0) {
|
|
|
|
return func + 6;
|
|
|
|
} else {
|
|
|
|
return func;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-09 23:57:08 +00:00
|
|
|
|
2012-07-02 21:42:53 +00:00
|
|
|
#define RETURN_TYPE_ERROR(isolate, dart_handle, type) \
|
|
|
|
do { \
|
|
|
|
const Object& tmp = \
|
|
|
|
Object::Handle(isolate, Api::UnwrapHandle((dart_handle))); \
|
|
|
|
if (tmp.IsNull()) { \
|
|
|
|
return Api::NewError("%s expects argument '%s' to be non-null.", \
|
|
|
|
CURRENT_FUNC, #dart_handle); \
|
|
|
|
} else if (tmp.IsError()) { \
|
|
|
|
return dart_handle; \
|
|
|
|
} else { \
|
|
|
|
return Api::NewError("%s expects argument '%s' to be of type %s.", \
|
|
|
|
CURRENT_FUNC, #dart_handle, #type); \
|
|
|
|
} \
|
2011-11-10 19:10:53 +00:00
|
|
|
} while (0)
|
|
|
|
|
|
|
|
|
2012-07-09 23:57:08 +00:00
|
|
|
#define RETURN_NULL_ERROR(parameter) \
|
|
|
|
return Api::NewError("%s expects argument '%s' to be non-null.", \
|
|
|
|
CURRENT_FUNC, #parameter);
|
|
|
|
|
|
|
|
|
2012-08-01 18:22:30 +00:00
|
|
|
#define CHECK_LENGTH(length, max_elements) \
|
|
|
|
do { \
|
|
|
|
intptr_t len = (length); \
|
|
|
|
intptr_t max = (max_elements); \
|
|
|
|
if (len < 0 || len > max) { \
|
|
|
|
return Api::NewError( \
|
2012-09-06 00:58:25 +00:00
|
|
|
"%s expects argument '%s' to be in the range [0..%"Pd"].", \
|
2012-08-01 18:22:30 +00:00
|
|
|
CURRENT_FUNC, #length, max); \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
2012-07-09 23:57:08 +00:00
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
// Return error if isolate is in an inconsistent state.
|
|
|
|
// Return NULL when no error condition exists.
|
2012-06-12 21:07:49 +00:00
|
|
|
//
|
|
|
|
// TODO(turnidge): Make this function return an error handle directly
|
|
|
|
// rather than returning an error string. The current behavior can
|
|
|
|
// cause compilation errors to appear to be api errors.
|
2012-08-23 00:27:49 +00:00
|
|
|
const char* CheckIsolateState(Isolate* isolate) {
|
|
|
|
if (ClassFinalizer::FinalizePendingClasses() &&
|
|
|
|
isolate->object_store()->PreallocateObjects()) {
|
|
|
|
// Success.
|
|
|
|
return NULL;
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
2012-03-03 01:53:26 +00:00
|
|
|
// Make a copy of the error message as the original message string
|
|
|
|
// may get deallocated when we return back from the Dart API call.
|
|
|
|
const Error& err = Error::Handle(isolate->object_store()->sticky_error());
|
|
|
|
const char* errmsg = err.ToErrorCString();
|
|
|
|
intptr_t errlen = strlen(errmsg) + 1;
|
2012-08-03 21:51:44 +00:00
|
|
|
char* msg = Api::TopScope(isolate)->zone()->Alloc<char>(errlen);
|
2012-03-03 01:53:26 +00:00
|
|
|
OS::SNPrint(msg, errlen, "%s", errmsg);
|
|
|
|
return msg;
|
2011-11-11 19:31:04 +00:00
|
|
|
}
|
|
|
|
|
2011-10-19 18:41:33 +00:00
|
|
|
|
2012-04-04 20:31:49 +00:00
|
|
|
void SetupErrorResult(Isolate* isolate, Dart_Handle* handle) {
|
2012-04-06 17:05:50 +00:00
|
|
|
*handle = Api::NewHandle(
|
2012-04-04 20:31:49 +00:00
|
|
|
isolate, Isolate::Current()->object_store()->sticky_error());
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-04-06 17:05:50 +00:00
|
|
|
Dart_Handle Api::NewHandle(Isolate* isolate, RawObject* raw) {
|
2012-08-03 21:51:44 +00:00
|
|
|
LocalHandles* local_handles = Api::TopScope(isolate)->local_handles();
|
2011-11-22 19:42:38 +00:00
|
|
|
ASSERT(local_handles != NULL);
|
|
|
|
LocalHandle* ref = local_handles->AllocateHandle();
|
2012-04-06 17:05:50 +00:00
|
|
|
ref->set_raw(raw);
|
2011-11-22 19:42:38 +00:00
|
|
|
return reinterpret_cast<Dart_Handle>(ref);
|
|
|
|
}
|
|
|
|
|
|
|
|
RawObject* Api::UnwrapHandle(Dart_Handle object) {
|
2012-07-09 23:57:08 +00:00
|
|
|
#if defined(DEBUG)
|
2011-11-22 19:42:38 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
ASSERT(isolate != NULL);
|
|
|
|
ApiState* state = isolate->api_state();
|
|
|
|
ASSERT(state != NULL);
|
2012-08-23 21:26:15 +00:00
|
|
|
ASSERT(state->IsValidLocalHandle(object) ||
|
2012-01-13 01:23:42 +00:00
|
|
|
state->IsValidPersistentHandle(object) ||
|
2012-08-23 21:26:15 +00:00
|
|
|
state->IsValidWeakPersistentHandle(object) ||
|
|
|
|
state->IsValidPrologueWeakPersistentHandle(object));
|
2012-03-13 23:41:59 +00:00
|
|
|
ASSERT(FinalizablePersistentHandle::raw_offset() == 0 &&
|
2012-01-13 01:23:42 +00:00
|
|
|
PersistentHandle::raw_offset() == 0 &&
|
2011-11-22 19:42:38 +00:00
|
|
|
LocalHandle::raw_offset() == 0);
|
|
|
|
#endif
|
2012-08-30 19:40:27 +00:00
|
|
|
return (reinterpret_cast<LocalHandle*>(object))->raw();
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
|
|
|
|
2012-07-02 21:42:53 +00:00
|
|
|
#define DEFINE_UNWRAP(type) \
|
|
|
|
const type& Api::Unwrap##type##Handle(Isolate* iso, \
|
|
|
|
Dart_Handle dart_handle) { \
|
|
|
|
const Object& obj = Object::Handle(iso, Api::UnwrapHandle(dart_handle)); \
|
|
|
|
if (obj.Is##type()) { \
|
|
|
|
return type::Cast(obj); \
|
|
|
|
} \
|
|
|
|
return type::Handle(iso); \
|
2011-11-11 19:31:04 +00:00
|
|
|
}
|
2012-11-05 22:22:19 +00:00
|
|
|
CLASS_LIST_FOR_HANDLES(DEFINE_UNWRAP)
|
2011-11-22 19:42:38 +00:00
|
|
|
#undef DEFINE_UNWRAP
|
|
|
|
|
|
|
|
|
|
|
|
LocalHandle* Api::UnwrapAsLocalHandle(const ApiState& state,
|
|
|
|
Dart_Handle object) {
|
|
|
|
ASSERT(state.IsValidLocalHandle(object));
|
|
|
|
return reinterpret_cast<LocalHandle*>(object);
|
2011-10-19 18:41:33 +00:00
|
|
|
}
|
|
|
|
|
2011-10-31 20:18:07 +00:00
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
PersistentHandle* Api::UnwrapAsPersistentHandle(const ApiState& state,
|
|
|
|
Dart_Handle object) {
|
|
|
|
ASSERT(state.IsValidPersistentHandle(object));
|
|
|
|
return reinterpret_cast<PersistentHandle*>(object);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-03-13 23:41:59 +00:00
|
|
|
FinalizablePersistentHandle* Api::UnwrapAsWeakPersistentHandle(
|
|
|
|
const ApiState& state,
|
|
|
|
Dart_Handle object) {
|
2012-01-13 01:23:42 +00:00
|
|
|
ASSERT(state.IsValidWeakPersistentHandle(object));
|
2012-03-13 23:41:59 +00:00
|
|
|
return reinterpret_cast<FinalizablePersistentHandle*>(object);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
FinalizablePersistentHandle* Api::UnwrapAsPrologueWeakPersistentHandle(
|
|
|
|
const ApiState& state,
|
|
|
|
Dart_Handle object) {
|
|
|
|
ASSERT(state.IsValidPrologueWeakPersistentHandle(object));
|
|
|
|
return reinterpret_cast<FinalizablePersistentHandle*>(object);
|
2012-01-13 01:23:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-12-01 18:18:06 +00:00
|
|
|
Dart_Isolate Api::CastIsolate(Isolate* isolate) {
|
|
|
|
return reinterpret_cast<Dart_Isolate>(isolate);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-04-04 20:31:49 +00:00
|
|
|
Dart_Handle Api::Success(Isolate* isolate) {
|
2011-11-22 19:42:38 +00:00
|
|
|
ASSERT(isolate != NULL);
|
|
|
|
ApiState* state = isolate->api_state();
|
|
|
|
ASSERT(state != NULL);
|
|
|
|
PersistentHandle* true_handle = state->True();
|
|
|
|
return reinterpret_cast<Dart_Handle>(true_handle);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-01-10 21:42:21 +00:00
|
|
|
Dart_Handle Api::NewError(const char* format, ...) {
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE_NOCHECKS(isolate);
|
2011-11-22 19:42:38 +00:00
|
|
|
|
|
|
|
va_list args;
|
|
|
|
va_start(args, format);
|
|
|
|
intptr_t len = OS::VSNPrint(NULL, 0, format, args);
|
|
|
|
va_end(args);
|
|
|
|
|
2012-10-16 22:05:40 +00:00
|
|
|
char* buffer = isolate->current_zone()->Alloc<char>(len + 1);
|
2011-11-22 19:42:38 +00:00
|
|
|
va_list args2;
|
|
|
|
va_start(args2, format);
|
|
|
|
OS::VSNPrint(buffer, (len + 1), format, args2);
|
|
|
|
va_end(args2);
|
|
|
|
|
2012-04-04 20:31:49 +00:00
|
|
|
const String& message = String::Handle(isolate, String::New(buffer));
|
2012-04-06 17:05:50 +00:00
|
|
|
return Api::NewHandle(isolate, ApiError::New(message));
|
2011-11-11 19:31:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-04-04 20:31:49 +00:00
|
|
|
Dart_Handle Api::Null(Isolate* isolate) {
|
2011-11-22 19:42:38 +00:00
|
|
|
ASSERT(isolate != NULL);
|
|
|
|
ApiState* state = isolate->api_state();
|
|
|
|
ASSERT(state != NULL);
|
|
|
|
PersistentHandle* null_handle = state->Null();
|
|
|
|
return reinterpret_cast<Dart_Handle>(null_handle);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-04-04 20:31:49 +00:00
|
|
|
Dart_Handle Api::True(Isolate* isolate) {
|
2011-11-22 19:42:38 +00:00
|
|
|
ASSERT(isolate != NULL);
|
|
|
|
ApiState* state = isolate->api_state();
|
|
|
|
ASSERT(state != NULL);
|
|
|
|
PersistentHandle* true_handle = state->True();
|
|
|
|
return reinterpret_cast<Dart_Handle>(true_handle);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-04-04 20:31:49 +00:00
|
|
|
Dart_Handle Api::False(Isolate* isolate) {
|
2011-11-22 19:42:38 +00:00
|
|
|
ASSERT(isolate != NULL);
|
|
|
|
ApiState* state = isolate->api_state();
|
|
|
|
ASSERT(state != NULL);
|
|
|
|
PersistentHandle* false_handle = state->False();
|
|
|
|
return reinterpret_cast<Dart_Handle>(false_handle);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-08-03 21:51:44 +00:00
|
|
|
ApiLocalScope* Api::TopScope(Isolate* isolate) {
|
2011-11-22 19:42:38 +00:00
|
|
|
ASSERT(isolate != NULL);
|
|
|
|
ApiState* state = isolate->api_state();
|
|
|
|
ASSERT(state != NULL);
|
|
|
|
ApiLocalScope* scope = state->top_scope();
|
|
|
|
ASSERT(scope != NULL);
|
2012-08-03 21:51:44 +00:00
|
|
|
return scope;
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-02-09 08:47:19 +00:00
|
|
|
void Api::InitOnce() {
|
|
|
|
ASSERT(api_native_key_ == Thread::kUnsetThreadLocalKey);
|
|
|
|
api_native_key_ = Thread::CreateThreadLocal();
|
|
|
|
ASSERT(api_native_key_ != Thread::kUnsetThreadLocalKey);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-08-30 00:17:52 +00:00
|
|
|
bool Api::ExternalStringGetPeerHelper(Dart_Handle object, void** peer) {
|
|
|
|
NoGCScope no_gc_scope;
|
|
|
|
RawObject* raw_obj = Api::UnwrapHandle(object);
|
|
|
|
switch (Api::ClassId(object)) {
|
|
|
|
case kExternalOneByteStringCid: {
|
|
|
|
RawExternalOneByteString* raw_string =
|
|
|
|
reinterpret_cast<RawExternalOneByteString*>(raw_obj)->ptr();
|
|
|
|
ExternalStringData<uint8_t>* data = raw_string->external_data_;
|
|
|
|
*peer = data->peer();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
case kExternalTwoByteStringCid: {
|
|
|
|
RawExternalTwoByteString* raw_string =
|
|
|
|
reinterpret_cast<RawExternalTwoByteString*>(raw_obj)->ptr();
|
|
|
|
ExternalStringData<uint16_t>* data = raw_string->external_data_;
|
|
|
|
*peer = data->peer();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-13 17:47:25 +00:00
|
|
|
// When we want to return a handle to a type to the user, we handle
|
|
|
|
// class-types differently than some other types.
|
|
|
|
static Dart_Handle TypeToHandle(Isolate* isolate,
|
|
|
|
const char* function_name,
|
|
|
|
const AbstractType& type) {
|
2012-10-10 20:54:49 +00:00
|
|
|
if (type.IsMalformed()) {
|
|
|
|
const Error& error = Error::Handle(type.malformed_error());
|
|
|
|
return Api::NewError("%s: malformed type encountered: %s.",
|
|
|
|
function_name, error.ToErrorCString());
|
|
|
|
} else if (type.HasResolvedTypeClass()) {
|
2012-09-13 17:47:25 +00:00
|
|
|
const Class& cls = Class::Handle(isolate, type.type_class());
|
|
|
|
#if defined(DEBUG)
|
|
|
|
const Library& lib = Library::Handle(cls.library());
|
|
|
|
if (lib.IsNull()) {
|
|
|
|
ASSERT(cls.IsDynamicClass() || cls.IsVoidClass());
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return Api::NewHandle(isolate, cls.raw());
|
|
|
|
} else if (type.IsTypeParameter()) {
|
|
|
|
return Api::NewHandle(isolate, type.raw());
|
|
|
|
} else {
|
|
|
|
return Api::NewError("%s: unexpected type '%s' encountered.",
|
|
|
|
function_name, type.ToCString());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
// --- Handles ---
|
|
|
|
|
|
|
|
|
2011-12-21 17:50:38 +00:00
|
|
|
DART_EXPORT bool Dart_IsError(Dart_Handle handle) {
|
2012-05-31 12:41:37 +00:00
|
|
|
return RawObject::IsErrorClassId(Api::ClassId(handle));
|
2011-10-31 20:18:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-06-12 21:07:49 +00:00
|
|
|
DART_EXPORT bool Dart_IsApiError(Dart_Handle object) {
|
2012-08-08 19:46:23 +00:00
|
|
|
return Api::ClassId(object) == kApiErrorCid;
|
2012-06-12 21:07:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT bool Dart_IsUnhandledExceptionError(Dart_Handle object) {
|
2012-08-08 19:46:23 +00:00
|
|
|
return Api::ClassId(object) == kUnhandledExceptionCid;
|
2012-06-12 21:07:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT bool Dart_IsCompilationError(Dart_Handle object) {
|
2012-08-08 19:46:23 +00:00
|
|
|
return Api::ClassId(object) == kLanguageErrorCid;
|
2012-06-12 21:07:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT bool Dart_IsFatalError(Dart_Handle object) {
|
2012-08-08 19:46:23 +00:00
|
|
|
return Api::ClassId(object) == kUnwindErrorCid;
|
2012-06-12 21:07:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-12-21 17:50:38 +00:00
|
|
|
DART_EXPORT const char* Dart_GetError(Dart_Handle handle) {
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(handle));
|
2012-01-12 01:01:46 +00:00
|
|
|
if (obj.IsError()) {
|
2012-07-02 21:42:53 +00:00
|
|
|
const Error& error = Error::Cast(obj);
|
2012-01-12 01:01:46 +00:00
|
|
|
const char* str = error.ToErrorCString();
|
|
|
|
intptr_t len = strlen(str) + 1;
|
2012-08-03 21:51:44 +00:00
|
|
|
char* str_copy = Api::TopScope(isolate)->zone()->Alloc<char>(len);
|
2012-01-12 01:01:46 +00:00
|
|
|
strncpy(str_copy, str, len);
|
2012-06-13 14:47:33 +00:00
|
|
|
// Strip a possible trailing '\n'.
|
|
|
|
if ((len > 1) && (str_copy[len - 2] == '\n')) {
|
|
|
|
str_copy[len - 2] = '\0';
|
|
|
|
}
|
2012-01-12 01:01:46 +00:00
|
|
|
return str_copy;
|
2011-11-11 19:31:04 +00:00
|
|
|
} else {
|
2012-01-12 01:01:46 +00:00
|
|
|
return "";
|
2011-11-11 19:31:04 +00:00
|
|
|
}
|
2011-10-19 18:41:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
DART_EXPORT bool Dart_ErrorHasException(Dart_Handle handle) {
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(handle));
|
2012-01-10 21:42:21 +00:00
|
|
|
return obj.IsUnhandledException();
|
2011-10-19 18:41:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_ErrorGetException(Dart_Handle handle) {
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(handle));
|
2012-01-10 21:42:21 +00:00
|
|
|
if (obj.IsUnhandledException()) {
|
2012-07-02 21:42:53 +00:00
|
|
|
const UnhandledException& error = UnhandledException::Cast(obj);
|
2012-04-06 17:05:50 +00:00
|
|
|
return Api::NewHandle(isolate, error.exception());
|
2012-01-10 21:42:21 +00:00
|
|
|
} else if (obj.IsError()) {
|
|
|
|
return Api::NewError("This error is not an unhandled exception error.");
|
2011-11-22 19:42:38 +00:00
|
|
|
} else {
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("Can only get exceptions from error handles.");
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_ErrorGetStacktrace(Dart_Handle handle) {
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(handle));
|
2012-01-10 21:42:21 +00:00
|
|
|
if (obj.IsUnhandledException()) {
|
2012-07-02 21:42:53 +00:00
|
|
|
const UnhandledException& error = UnhandledException::Cast(obj);
|
2012-04-06 17:05:50 +00:00
|
|
|
return Api::NewHandle(isolate, error.stacktrace());
|
2012-01-10 21:42:21 +00:00
|
|
|
} else if (obj.IsError()) {
|
|
|
|
return Api::NewError("This error is not an unhandled exception error.");
|
2011-11-22 19:42:38 +00:00
|
|
|
} else {
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("Can only get stacktraces from error handles.");
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-06-12 21:07:49 +00:00
|
|
|
// Deprecated.
|
|
|
|
// TODO(turnidge): Remove all uses and delete.
|
|
|
|
DART_EXPORT Dart_Handle Dart_Error(const char* format, ...) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
|
|
|
|
va_list args;
|
|
|
|
va_start(args, format);
|
|
|
|
intptr_t len = OS::VSNPrint(NULL, 0, format, args);
|
|
|
|
va_end(args);
|
|
|
|
|
2012-10-16 22:05:40 +00:00
|
|
|
char* buffer = isolate->current_zone()->Alloc<char>(len + 1);
|
2012-06-12 21:07:49 +00:00
|
|
|
va_list args2;
|
|
|
|
va_start(args2, format);
|
|
|
|
OS::VSNPrint(buffer, (len + 1), format, args2);
|
|
|
|
va_end(args2);
|
|
|
|
|
|
|
|
const String& message = String::Handle(isolate, String::New(buffer));
|
|
|
|
return Api::NewHandle(isolate, ApiError::New(message));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-01-10 21:42:21 +00:00
|
|
|
// TODO(turnidge): This clones Api::NewError. I need to use va_copy to
|
2011-11-22 19:42:38 +00:00
|
|
|
// fix this but not sure if it available on all of our builds.
|
2012-06-12 21:07:49 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_NewApiError(const char* format, ...) {
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
2011-11-22 19:42:38 +00:00
|
|
|
|
|
|
|
va_list args;
|
|
|
|
va_start(args, format);
|
|
|
|
intptr_t len = OS::VSNPrint(NULL, 0, format, args);
|
|
|
|
va_end(args);
|
|
|
|
|
2012-10-16 22:05:40 +00:00
|
|
|
char* buffer = isolate->current_zone()->Alloc<char>(len + 1);
|
2011-11-22 19:42:38 +00:00
|
|
|
va_list args2;
|
|
|
|
va_start(args2, format);
|
|
|
|
OS::VSNPrint(buffer, (len + 1), format, args2);
|
|
|
|
va_end(args2);
|
|
|
|
|
2012-04-04 20:31:49 +00:00
|
|
|
const String& message = String::Handle(isolate, String::New(buffer));
|
2012-04-06 17:05:50 +00:00
|
|
|
return Api::NewHandle(isolate, ApiError::New(message));
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-06-12 21:07:49 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_NewUnhandledExceptionError(Dart_Handle exception) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
const Instance& obj = Api::UnwrapInstanceHandle(isolate, exception);
|
|
|
|
if (obj.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, exception, Instance);
|
|
|
|
}
|
|
|
|
const Instance& stacktrace = Instance::Handle(isolate);
|
|
|
|
return Api::NewHandle(isolate, UnhandledException::New(obj, stacktrace));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-02-02 19:05:06 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_PropagateError(Dart_Handle handle) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
2012-10-18 22:33:45 +00:00
|
|
|
{
|
|
|
|
const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(handle));
|
|
|
|
if (!obj.IsError()) {
|
|
|
|
return Api::NewError(
|
|
|
|
"%s expects argument 'handle' to be an error handle. "
|
|
|
|
"Did you forget to check Dart_IsError first?",
|
|
|
|
CURRENT_FUNC);
|
|
|
|
}
|
2012-02-02 19:05:06 +00:00
|
|
|
}
|
|
|
|
if (isolate->top_exit_frame_info() == 0) {
|
|
|
|
// There are no dart frames on the stack so it would be illegal to
|
|
|
|
// propagate an error here.
|
|
|
|
return Api::NewError("No Dart frames on stack, cannot propagate error.");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Unwind all the API scopes till the exit frame before propagating.
|
|
|
|
ApiState* state = isolate->api_state();
|
|
|
|
ASSERT(state != NULL);
|
2012-10-16 22:05:40 +00:00
|
|
|
const Error* error;
|
|
|
|
{
|
|
|
|
// We need to preserve the error object across the destruction of zones
|
|
|
|
// when the ApiScopes are unwound. By using NoGCScope, we can ensure
|
|
|
|
// that GC won't touch the raw error object before creating a valid
|
|
|
|
// handle for it in the surviving zone.
|
|
|
|
NoGCScope no_gc;
|
2012-10-18 22:33:45 +00:00
|
|
|
RawError* raw_error = Api::UnwrapErrorHandle(isolate, handle).raw();
|
2012-10-16 22:05:40 +00:00
|
|
|
state->UnwindScopes(isolate->top_exit_frame_info());
|
|
|
|
error = &Error::Handle(isolate, raw_error);
|
|
|
|
}
|
|
|
|
Exceptions::PropagateError(*error);
|
2012-02-02 19:05:06 +00:00
|
|
|
UNREACHABLE();
|
|
|
|
return Api::NewError("Cannot reach here. Internal error.");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
DART_EXPORT void _Dart_ReportErrorHandle(const char* file,
|
2012-05-14 17:58:59 +00:00
|
|
|
int line,
|
|
|
|
const char* handle,
|
|
|
|
const char* message) {
|
2011-11-22 19:42:38 +00:00
|
|
|
fprintf(stderr, "%s:%d: error handle: '%s':\n '%s'\n",
|
|
|
|
file, line, handle, message);
|
|
|
|
OS::Abort();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_ToString(Dart_Handle object) {
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(object));
|
2011-11-22 19:42:38 +00:00
|
|
|
if (obj.IsString()) {
|
2012-04-06 17:05:50 +00:00
|
|
|
return Api::NewHandle(isolate, obj.raw());
|
2011-11-22 19:42:38 +00:00
|
|
|
} else if (obj.IsInstance()) {
|
2012-07-02 21:42:53 +00:00
|
|
|
const Instance& receiver = Instance::Cast(obj);
|
2012-04-06 17:05:50 +00:00
|
|
|
return Api::NewHandle(isolate, DartLibraryCalls::ToString(receiver));
|
2011-11-22 19:42:38 +00:00
|
|
|
} else {
|
|
|
|
// This is a VM internal object. Call the C++ method of printing.
|
2012-04-06 17:05:50 +00:00
|
|
|
return Api::NewHandle(isolate, String::New(obj.ToCString()));
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-05-15 18:34:58 +00:00
|
|
|
DART_EXPORT bool Dart_IdentityEquals(Dart_Handle obj1, Dart_Handle obj2) {
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
2012-05-15 18:34:58 +00:00
|
|
|
CHECK_ISOLATE(isolate);
|
|
|
|
NoGCScope ngc;
|
|
|
|
return Api::UnwrapHandle(obj1) == Api::UnwrapHandle(obj2);
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-01-13 01:23:42 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_NewPersistentHandle(Dart_Handle object) {
|
2011-11-22 19:42:38 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
2011-12-01 19:17:10 +00:00
|
|
|
CHECK_ISOLATE(isolate);
|
|
|
|
DARTSCOPE_NOCHECKS(isolate);
|
2011-11-22 19:42:38 +00:00
|
|
|
ApiState* state = isolate->api_state();
|
|
|
|
ASSERT(state != NULL);
|
2012-04-04 20:31:49 +00:00
|
|
|
const Object& old_ref = Object::Handle(isolate, Api::UnwrapHandle(object));
|
2011-11-22 19:42:38 +00:00
|
|
|
PersistentHandle* new_ref = state->persistent_handles().AllocateHandle();
|
|
|
|
new_ref->set_raw(old_ref);
|
2011-12-20 01:44:53 +00:00
|
|
|
return reinterpret_cast<Dart_Handle>(new_ref);
|
|
|
|
}
|
|
|
|
|
2012-03-13 23:41:59 +00:00
|
|
|
static Dart_Handle AllocateFinalizableHandle(
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate,
|
2012-03-13 23:41:59 +00:00
|
|
|
FinalizablePersistentHandles* handles,
|
|
|
|
Dart_Handle object,
|
|
|
|
void* peer,
|
|
|
|
Dart_WeakPersistentHandleFinalizer callback) {
|
2012-04-04 20:31:49 +00:00
|
|
|
const Object& ref = Object::Handle(isolate, Api::UnwrapHandle(object));
|
2012-03-13 23:41:59 +00:00
|
|
|
FinalizablePersistentHandle* finalizable_ref = handles->AllocateHandle();
|
|
|
|
finalizable_ref->set_raw(ref);
|
|
|
|
finalizable_ref->set_peer(peer);
|
|
|
|
finalizable_ref->set_callback(callback);
|
|
|
|
return reinterpret_cast<Dart_Handle>(finalizable_ref);
|
|
|
|
}
|
|
|
|
|
2011-12-20 01:44:53 +00:00
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_NewWeakPersistentHandle(
|
|
|
|
Dart_Handle object,
|
|
|
|
void* peer,
|
2012-02-11 04:34:44 +00:00
|
|
|
Dart_WeakPersistentHandleFinalizer callback) {
|
2012-01-13 01:23:42 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
CHECK_ISOLATE(isolate);
|
|
|
|
DARTSCOPE_NOCHECKS(isolate);
|
|
|
|
ApiState* state = isolate->api_state();
|
|
|
|
ASSERT(state != NULL);
|
2012-04-04 20:31:49 +00:00
|
|
|
return AllocateFinalizableHandle(isolate,
|
|
|
|
&state->weak_persistent_handles(),
|
2012-03-13 23:41:59 +00:00
|
|
|
object,
|
|
|
|
peer,
|
|
|
|
callback);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_NewPrologueWeakPersistentHandle(
|
|
|
|
Dart_Handle object,
|
|
|
|
void* peer,
|
|
|
|
Dart_WeakPersistentHandleFinalizer callback) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
CHECK_ISOLATE(isolate);
|
|
|
|
DARTSCOPE_NOCHECKS(isolate);
|
|
|
|
ApiState* state = isolate->api_state();
|
|
|
|
ASSERT(state != NULL);
|
2012-04-04 20:31:49 +00:00
|
|
|
return AllocateFinalizableHandle(isolate,
|
|
|
|
&state->prologue_weak_persistent_handles(),
|
2012-03-13 23:41:59 +00:00
|
|
|
object,
|
|
|
|
peer,
|
|
|
|
callback);
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT void Dart_DeletePersistentHandle(Dart_Handle object) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
2011-12-01 19:17:10 +00:00
|
|
|
CHECK_ISOLATE(isolate);
|
2011-11-22 19:42:38 +00:00
|
|
|
ApiState* state = isolate->api_state();
|
|
|
|
ASSERT(state != NULL);
|
2012-03-13 23:41:59 +00:00
|
|
|
if (state->IsValidPrologueWeakPersistentHandle(object)) {
|
|
|
|
FinalizablePersistentHandle* prologue_weak_ref =
|
|
|
|
Api::UnwrapAsPrologueWeakPersistentHandle(*state, object);
|
|
|
|
state->prologue_weak_persistent_handles().FreeHandle(prologue_weak_ref);
|
|
|
|
return;
|
|
|
|
}
|
2012-01-13 01:23:42 +00:00
|
|
|
if (state->IsValidWeakPersistentHandle(object)) {
|
2012-03-13 23:41:59 +00:00
|
|
|
FinalizablePersistentHandle* weak_ref =
|
2012-01-13 01:23:42 +00:00
|
|
|
Api::UnwrapAsWeakPersistentHandle(*state, object);
|
|
|
|
state->weak_persistent_handles().FreeHandle(weak_ref);
|
2012-03-13 23:41:59 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
PersistentHandle* ref = Api::UnwrapAsPersistentHandle(*state, object);
|
|
|
|
ASSERT(!state->IsProtectedHandle(ref));
|
|
|
|
if (!state->IsProtectedHandle(ref)) {
|
|
|
|
state->persistent_handles().FreeHandle(ref);
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-12-20 01:44:53 +00:00
|
|
|
DART_EXPORT bool Dart_IsWeakPersistentHandle(Dart_Handle object) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
CHECK_ISOLATE(isolate);
|
|
|
|
ApiState* state = isolate->api_state();
|
|
|
|
ASSERT(state != NULL);
|
2012-01-13 01:23:42 +00:00
|
|
|
return state->IsValidWeakPersistentHandle(object);
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-03-13 23:41:59 +00:00
|
|
|
DART_EXPORT bool Dart_IsPrologueWeakPersistentHandle(Dart_Handle object) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
CHECK_ISOLATE(isolate);
|
|
|
|
ApiState* state = isolate->api_state();
|
|
|
|
ASSERT(state != NULL);
|
|
|
|
return state->IsValidPrologueWeakPersistentHandle(object);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-03-03 02:30:20 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_NewWeakReferenceSet(Dart_Handle* keys,
|
|
|
|
intptr_t num_keys,
|
|
|
|
Dart_Handle* values,
|
|
|
|
intptr_t num_values) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
CHECK_ISOLATE(isolate);
|
|
|
|
ApiState* state = isolate->api_state();
|
|
|
|
ASSERT(state != NULL);
|
|
|
|
if (keys == NULL) {
|
2012-07-09 23:57:08 +00:00
|
|
|
RETURN_NULL_ERROR(keys);
|
2012-03-03 02:30:20 +00:00
|
|
|
}
|
|
|
|
if (num_keys <= 0) {
|
|
|
|
return Api::NewError(
|
|
|
|
"%s expects argument 'num_keys' to be greater than 0.",
|
|
|
|
CURRENT_FUNC);
|
|
|
|
}
|
|
|
|
if (values == NULL) {
|
2012-07-09 23:57:08 +00:00
|
|
|
RETURN_NULL_ERROR(values);
|
2012-03-03 02:30:20 +00:00
|
|
|
}
|
|
|
|
if (num_values <= 0) {
|
|
|
|
return Api::NewError(
|
|
|
|
"%s expects argument 'num_values' to be greater than 0.",
|
|
|
|
CURRENT_FUNC);
|
|
|
|
}
|
|
|
|
|
2012-07-26 23:52:20 +00:00
|
|
|
WeakReferenceSet* reference_set = new WeakReferenceSet(keys, num_keys,
|
|
|
|
values, num_values);
|
|
|
|
state->DelayWeakReferenceSet(reference_set);
|
2012-04-04 20:31:49 +00:00
|
|
|
return Api::Success(isolate);
|
2012-03-03 02:30:20 +00:00
|
|
|
}
|
|
|
|
|
2012-03-07 19:38:51 +00:00
|
|
|
|
|
|
|
// --- Garbage Collection Callbacks --
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_AddGcPrologueCallback(
|
|
|
|
Dart_GcPrologueCallback callback) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
CHECK_ISOLATE(isolate);
|
|
|
|
GcPrologueCallbacks& callbacks = isolate->gc_prologue_callbacks();
|
|
|
|
if (callbacks.Contains(callback)) {
|
|
|
|
return Api::NewError(
|
|
|
|
"%s permits only one instance of 'callback' to be present in the "
|
|
|
|
"prologue callback list.",
|
|
|
|
CURRENT_FUNC);
|
|
|
|
}
|
|
|
|
callbacks.Add(callback);
|
2012-04-04 20:31:49 +00:00
|
|
|
return Api::Success(isolate);
|
2012-03-07 19:38:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_RemoveGcPrologueCallback(
|
|
|
|
Dart_GcPrologueCallback callback) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
CHECK_ISOLATE(isolate);
|
|
|
|
GcPrologueCallbacks& callbacks = isolate->gc_prologue_callbacks();
|
|
|
|
if (!callbacks.Contains(callback)) {
|
|
|
|
return Api::NewError(
|
|
|
|
"%s expects 'callback' to be present in the prologue callback list.",
|
|
|
|
CURRENT_FUNC);
|
|
|
|
}
|
|
|
|
callbacks.Remove(callback);
|
2012-04-04 20:31:49 +00:00
|
|
|
return Api::Success(isolate);
|
2012-03-07 19:38:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_AddGcEpilogueCallback(
|
|
|
|
Dart_GcEpilogueCallback callback) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
CHECK_ISOLATE(isolate);
|
|
|
|
GcEpilogueCallbacks& callbacks = isolate->gc_epilogue_callbacks();
|
|
|
|
if (callbacks.Contains(callback)) {
|
|
|
|
return Api::NewError(
|
|
|
|
"%s permits only one instance of 'callback' to be present in the "
|
|
|
|
"epilogue callback list.",
|
|
|
|
CURRENT_FUNC);
|
|
|
|
}
|
|
|
|
callbacks.Add(callback);
|
2012-04-04 20:31:49 +00:00
|
|
|
return Api::Success(isolate);
|
2012-03-07 19:38:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_RemoveGcEpilogueCallback(
|
|
|
|
Dart_GcEpilogueCallback callback) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
CHECK_ISOLATE(isolate);
|
|
|
|
GcEpilogueCallbacks& callbacks = isolate->gc_epilogue_callbacks();
|
|
|
|
if (!callbacks.Contains(callback)) {
|
|
|
|
return Api::NewError(
|
|
|
|
"%s expects 'callback' to be present in the epilogue callback list.",
|
|
|
|
CURRENT_FUNC);
|
|
|
|
}
|
|
|
|
callbacks.Remove(callback);
|
2012-04-04 20:31:49 +00:00
|
|
|
return Api::Success(isolate);
|
2012-03-07 19:38:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-12-06 21:56:31 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_HeapProfile(Dart_FileWriteCallback callback,
|
2012-06-14 00:08:07 +00:00
|
|
|
void* stream) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
CHECK_ISOLATE(isolate);
|
|
|
|
if (callback == NULL) {
|
2012-07-09 23:57:08 +00:00
|
|
|
RETURN_NULL_ERROR(callback);
|
2012-06-14 00:08:07 +00:00
|
|
|
}
|
|
|
|
isolate->heap()->Profile(callback, stream);
|
|
|
|
return Api::Success(isolate);
|
|
|
|
}
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
// --- Initialization and Globals ---
|
|
|
|
|
2012-10-11 07:17:09 +00:00
|
|
|
DART_EXPORT const char* Dart_VersionString() {
|
|
|
|
return Version::String();
|
|
|
|
}
|
2011-11-22 19:42:38 +00:00
|
|
|
|
2012-11-26 23:31:47 +00:00
|
|
|
DART_EXPORT bool Dart_Initialize(
|
|
|
|
Dart_IsolateCreateCallback create,
|
|
|
|
Dart_IsolateInterruptCallback interrupt,
|
|
|
|
Dart_IsolateUnhandledExceptionCallback unhandled,
|
2012-12-06 21:56:31 +00:00
|
|
|
Dart_IsolateShutdownCallback shutdown,
|
|
|
|
Dart_FileOpenCallback file_open,
|
|
|
|
Dart_FileWriteCallback file_write,
|
|
|
|
Dart_FileCloseCallback file_close) {
|
|
|
|
const char* err_msg = Dart::InitOnce(create, interrupt, unhandled, shutdown,
|
|
|
|
file_open, file_write, file_close);
|
2012-11-22 07:54:21 +00:00
|
|
|
if (err_msg != NULL) {
|
|
|
|
OS::PrintErr("Dart_Initialize: %s\n", err_msg);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
|
|
|
|
2011-12-01 11:59:35 +00:00
|
|
|
DART_EXPORT bool Dart_SetVMFlags(int argc, const char** argv) {
|
|
|
|
return Flags::ProcessCommandLineFlags(argc, argv);
|
|
|
|
}
|
2011-11-22 19:42:38 +00:00
|
|
|
|
|
|
|
DART_EXPORT bool Dart_IsVMFlagSet(const char* flag_name) {
|
|
|
|
if (Flags::Lookup(flag_name) != NULL) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// --- Isolates ---
|
2011-10-05 05:20:07 +00:00
|
|
|
|
|
|
|
|
2012-05-23 18:32:51 +00:00
|
|
|
static char* BuildIsolateName(const char* script_uri,
|
|
|
|
const char* main) {
|
|
|
|
if (script_uri == NULL) {
|
|
|
|
// Just use the main as the name.
|
|
|
|
if (main == NULL) {
|
|
|
|
return strdup("isolate");
|
|
|
|
} else {
|
|
|
|
return strdup(main);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Skip past any slashes and backslashes in the script uri.
|
|
|
|
const char* last_slash = strrchr(script_uri, '/');
|
|
|
|
if (last_slash != NULL) {
|
|
|
|
script_uri = last_slash + 1;
|
|
|
|
}
|
|
|
|
const char* last_backslash = strrchr(script_uri, '\\');
|
|
|
|
if (last_backslash != NULL) {
|
|
|
|
script_uri = last_backslash + 1;
|
|
|
|
}
|
|
|
|
if (main == NULL) {
|
|
|
|
main = "main";
|
|
|
|
}
|
|
|
|
|
|
|
|
char* chars = NULL;
|
|
|
|
intptr_t len = OS::SNPrint(NULL, 0, "%s/%s", script_uri, main) + 1;
|
|
|
|
chars = reinterpret_cast<char*>(malloc(len));
|
|
|
|
OS::SNPrint(chars, len, "%s/%s", script_uri, main);
|
|
|
|
return chars;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Isolate Dart_CreateIsolate(const char* script_uri,
|
|
|
|
const char* main,
|
2012-01-18 21:46:27 +00:00
|
|
|
const uint8_t* snapshot,
|
2011-12-01 00:30:25 +00:00
|
|
|
void* callback_data,
|
|
|
|
char** error) {
|
2012-05-23 18:32:51 +00:00
|
|
|
char* isolate_name = BuildIsolateName(script_uri, main);
|
|
|
|
Isolate* isolate = Dart::CreateIsolate(isolate_name);
|
|
|
|
free(isolate_name);
|
2012-03-12 22:56:24 +00:00
|
|
|
{
|
2012-10-17 18:06:26 +00:00
|
|
|
StackZone zone(isolate);
|
2012-03-12 22:56:24 +00:00
|
|
|
DARTSCOPE_NOCHECKS(isolate);
|
|
|
|
const Error& error_obj =
|
2012-04-04 20:31:49 +00:00
|
|
|
Error::Handle(isolate,
|
|
|
|
Dart::InitializeIsolate(snapshot, callback_data));
|
2012-03-12 22:56:24 +00:00
|
|
|
if (error_obj.IsNull()) {
|
|
|
|
START_TIMER(time_total_runtime);
|
|
|
|
return reinterpret_cast<Dart_Isolate>(isolate);
|
|
|
|
}
|
2012-02-02 19:05:06 +00:00
|
|
|
*error = strdup(error_obj.ToErrorCString());
|
2011-11-04 22:08:13 +00:00
|
|
|
}
|
2012-03-12 22:56:24 +00:00
|
|
|
Dart::ShutdownIsolate();
|
|
|
|
return reinterpret_cast<Dart_Isolate>(NULL);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT void Dart_ShutdownIsolate() {
|
2011-12-01 19:17:10 +00:00
|
|
|
CHECK_ISOLATE(Isolate::Current());
|
2011-10-05 05:20:07 +00:00
|
|
|
STOP_TIMER(time_total_runtime);
|
|
|
|
Dart::ShutdownIsolate();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Isolate Dart_CurrentIsolate() {
|
2011-12-01 18:18:06 +00:00
|
|
|
return Api::CastIsolate(Isolate::Current());
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-06-28 21:28:12 +00:00
|
|
|
DART_EXPORT void* Dart_CurrentIsolateData() {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
CHECK_ISOLATE(isolate);
|
|
|
|
return isolate->init_callback_data();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-05-30 17:07:19 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_DebugName() {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
CHECK_ISOLATE(isolate);
|
|
|
|
return Api::NewHandle(isolate, String::New(isolate->name()));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-10-05 05:20:07 +00:00
|
|
|
DART_EXPORT void Dart_EnterIsolate(Dart_Isolate dart_isolate) {
|
2011-12-01 19:17:10 +00:00
|
|
|
CHECK_NO_ISOLATE(Isolate::Current());
|
2011-10-05 05:20:07 +00:00
|
|
|
Isolate* isolate = reinterpret_cast<Isolate*>(dart_isolate);
|
|
|
|
Isolate::SetCurrent(isolate);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT void Dart_ExitIsolate() {
|
2011-12-01 19:17:10 +00:00
|
|
|
CHECK_ISOLATE(Isolate::Current());
|
2011-10-05 05:20:07 +00:00
|
|
|
Isolate::SetCurrent(NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-04-04 20:31:49 +00:00
|
|
|
static uint8_t* ApiReallocate(uint8_t* ptr,
|
|
|
|
intptr_t old_size,
|
|
|
|
intptr_t new_size) {
|
2012-08-03 21:51:44 +00:00
|
|
|
return Api::TopScope(Isolate::Current())->zone()->Realloc<uint8_t>(
|
|
|
|
ptr, old_size, new_size);
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-12-06 00:34:49 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_CreateSnapshot(uint8_t** buffer,
|
|
|
|
intptr_t* size) {
|
2011-11-22 19:42:38 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
2011-12-20 02:04:24 +00:00
|
|
|
TIMERSCOPE(time_creating_snapshot);
|
2011-12-06 00:34:49 +00:00
|
|
|
if (buffer == NULL) {
|
2012-07-09 23:57:08 +00:00
|
|
|
RETURN_NULL_ERROR(buffer);
|
2011-12-06 00:34:49 +00:00
|
|
|
}
|
|
|
|
if (size == NULL) {
|
2012-07-09 23:57:08 +00:00
|
|
|
RETURN_NULL_ERROR(size);
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
2012-08-23 00:27:49 +00:00
|
|
|
const char* msg = CheckIsolateState(isolate);
|
2011-11-22 19:42:38 +00:00
|
|
|
if (msg != NULL) {
|
2012-09-06 00:58:25 +00:00
|
|
|
return Api::NewError("%s", msg);
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
|
|
|
// Since this is only a snapshot the root library should not be set.
|
2012-04-04 20:31:49 +00:00
|
|
|
isolate->object_store()->set_root_library(Library::Handle(isolate));
|
2012-08-27 20:25:44 +00:00
|
|
|
FullSnapshotWriter writer(buffer, ApiReallocate);
|
2011-11-22 19:42:38 +00:00
|
|
|
writer.WriteFullSnapshot();
|
2011-12-21 19:37:37 +00:00
|
|
|
*size = writer.BytesWritten();
|
2012-04-04 20:31:49 +00:00
|
|
|
return Api::Success(isolate);
|
2011-12-06 00:34:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-12-20 02:04:24 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_CreateScriptSnapshot(uint8_t** buffer,
|
2011-12-06 00:34:49 +00:00
|
|
|
intptr_t* size) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
2011-12-20 02:04:24 +00:00
|
|
|
TIMERSCOPE(time_creating_snapshot);
|
2011-12-06 00:34:49 +00:00
|
|
|
if (buffer == NULL) {
|
2012-07-09 23:57:08 +00:00
|
|
|
RETURN_NULL_ERROR(buffer);
|
2011-12-06 00:34:49 +00:00
|
|
|
}
|
|
|
|
if (size == NULL) {
|
2012-07-09 23:57:08 +00:00
|
|
|
RETURN_NULL_ERROR(size);
|
2011-12-06 00:34:49 +00:00
|
|
|
}
|
|
|
|
const char* msg = CheckIsolateState(isolate);
|
|
|
|
if (msg != NULL) {
|
2012-09-06 00:58:25 +00:00
|
|
|
return Api::NewError("%s", msg);
|
2011-12-06 00:34:49 +00:00
|
|
|
}
|
2012-04-04 20:31:49 +00:00
|
|
|
Library& library =
|
|
|
|
Library::Handle(isolate, isolate->object_store()->root_library());
|
2011-12-20 02:04:24 +00:00
|
|
|
if (library.IsNull()) {
|
2012-01-10 21:42:21 +00:00
|
|
|
return
|
|
|
|
Api::NewError("%s expects the isolate to have a script loaded in it.",
|
2011-12-20 02:04:24 +00:00
|
|
|
CURRENT_FUNC);
|
|
|
|
}
|
2012-04-04 20:31:49 +00:00
|
|
|
ScriptSnapshotWriter writer(buffer, ApiReallocate);
|
2011-12-20 02:04:24 +00:00
|
|
|
writer.WriteScriptSnapshot(library);
|
2011-12-21 19:37:37 +00:00
|
|
|
*size = writer.BytesWritten();
|
2012-04-04 20:31:49 +00:00
|
|
|
return Api::Success(isolate);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-12-16 18:41:20 +00:00
|
|
|
DART_EXPORT void Dart_InterruptIsolate(Dart_Isolate isolate) {
|
|
|
|
if (isolate == NULL) {
|
|
|
|
FATAL1("%s expects argument 'isolate' to be non-null.", CURRENT_FUNC);
|
|
|
|
}
|
|
|
|
Isolate* iso = reinterpret_cast<Isolate*>(isolate);
|
|
|
|
iso->ScheduleInterrupts(Isolate::kApiInterrupt);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
// --- Messages and Ports ---
|
|
|
|
|
2012-01-24 19:31:01 +00:00
|
|
|
DART_EXPORT void Dart_SetMessageNotifyCallback(
|
|
|
|
Dart_MessageNotifyCallback message_notify_callback) {
|
2011-10-18 17:54:07 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
2011-12-01 19:17:10 +00:00
|
|
|
CHECK_ISOLATE(isolate);
|
2012-01-24 19:31:01 +00:00
|
|
|
isolate->set_message_notify_callback(message_notify_callback);
|
2011-10-18 17:54:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-04-19 19:47:27 +00:00
|
|
|
struct RunLoopData {
|
|
|
|
Monitor* monitor;
|
|
|
|
bool done;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static void RunLoopDone(uword param) {
|
|
|
|
RunLoopData* data = reinterpret_cast<RunLoopData*>(param);
|
|
|
|
ASSERT(data->monitor != NULL);
|
|
|
|
MonitorLocker ml(data->monitor);
|
|
|
|
data->done = true;
|
|
|
|
ml.Notify();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-12-14 18:27:58 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_RunLoop() {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
2012-04-19 19:47:27 +00:00
|
|
|
|
2011-12-14 18:27:58 +00:00
|
|
|
DARTSCOPE(isolate);
|
2012-04-19 19:47:27 +00:00
|
|
|
Monitor monitor;
|
|
|
|
MonitorLocker ml(&monitor);
|
|
|
|
{
|
|
|
|
SwitchIsolateScope switch_scope(NULL);
|
|
|
|
|
|
|
|
RunLoopData data;
|
|
|
|
data.monitor = &monitor;
|
|
|
|
data.done = false;
|
|
|
|
isolate->message_handler()->Run(
|
|
|
|
Dart::thread_pool(),
|
|
|
|
NULL, RunLoopDone, reinterpret_cast<uword>(&data));
|
|
|
|
while (!data.done) {
|
|
|
|
ml.Wait();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const Object& obj = Object::Handle(isolate->object_store()->sticky_error());
|
|
|
|
isolate->object_store()->clear_sticky_error();
|
2012-02-02 19:05:06 +00:00
|
|
|
if (obj.IsError()) {
|
2012-04-06 17:05:50 +00:00
|
|
|
return Api::NewHandle(isolate, obj.raw());
|
2011-12-14 18:27:58 +00:00
|
|
|
}
|
2012-02-02 19:05:06 +00:00
|
|
|
ASSERT(obj.IsNull());
|
2012-05-01 09:20:40 +00:00
|
|
|
if (FLAG_print_class_table) {
|
|
|
|
isolate->class_table()->Print();
|
|
|
|
}
|
2012-04-04 20:31:49 +00:00
|
|
|
return Api::Success(isolate);
|
2011-12-14 18:27:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-01-24 19:31:01 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_HandleMessage() {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
2012-04-19 19:47:27 +00:00
|
|
|
CHECK_ISOLATE(isolate);
|
|
|
|
if (!isolate->message_handler()->HandleNextMessage()) {
|
|
|
|
// TODO(turnidge): Clear sticky error here?
|
|
|
|
return Api::NewHandle(isolate, isolate->object_store()->sticky_error());
|
|
|
|
}
|
2012-04-04 20:31:49 +00:00
|
|
|
return Api::Success(isolate);
|
2011-10-18 17:54:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-29 21:55:13 +00:00
|
|
|
DART_EXPORT bool Dart_HasLivePorts() {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
ASSERT(isolate);
|
2012-02-01 18:53:40 +00:00
|
|
|
return isolate->message_handler()->HasLivePorts();
|
2011-11-29 21:55:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
static uint8_t* allocator(uint8_t* ptr, intptr_t old_size, intptr_t new_size) {
|
|
|
|
void* new_ptr = realloc(reinterpret_cast<void*>(ptr), new_size);
|
|
|
|
return reinterpret_cast<uint8_t*>(new_ptr);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-29 21:55:13 +00:00
|
|
|
DART_EXPORT bool Dart_PostIntArray(Dart_Port port_id,
|
2011-11-22 19:42:38 +00:00
|
|
|
intptr_t len,
|
|
|
|
intptr_t* data) {
|
|
|
|
uint8_t* buffer = NULL;
|
2012-02-18 10:10:28 +00:00
|
|
|
ApiMessageWriter writer(&buffer, &allocator);
|
2011-11-22 19:42:38 +00:00
|
|
|
writer.WriteMessage(len, data);
|
2011-10-05 05:20:07 +00:00
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
// Post the message at the given port.
|
2012-01-24 19:31:01 +00:00
|
|
|
return PortMap::PostMessage(new Message(
|
2012-08-27 20:25:44 +00:00
|
|
|
port_id, Message::kIllegalPort, buffer, writer.BytesWritten(),
|
|
|
|
Message::kNormalPriority));
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-11-15 08:16:27 +00:00
|
|
|
DART_EXPORT bool Dart_PostCObject(Dart_Port port_id, Dart_CObject* message) {
|
2012-02-06 15:42:15 +00:00
|
|
|
uint8_t* buffer = NULL;
|
2012-02-18 10:10:28 +00:00
|
|
|
ApiMessageWriter writer(&buffer, allocator);
|
2012-11-14 13:01:57 +00:00
|
|
|
bool success = writer.WriteCMessage(message);
|
|
|
|
|
|
|
|
if (!success) return success;
|
2012-02-06 15:42:15 +00:00
|
|
|
|
|
|
|
// Post the message at the given port.
|
|
|
|
return PortMap::PostMessage(new Message(
|
2012-08-27 20:25:44 +00:00
|
|
|
port_id, Message::kIllegalPort, buffer, writer.BytesWritten(),
|
|
|
|
Message::kNormalPriority));
|
2012-02-06 15:42:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-29 21:55:13 +00:00
|
|
|
DART_EXPORT bool Dart_Post(Dart_Port port_id, Dart_Handle handle) {
|
2011-12-01 19:17:10 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
CHECK_ISOLATE(isolate);
|
|
|
|
DARTSCOPE_NOCHECKS(isolate);
|
2012-04-04 20:31:49 +00:00
|
|
|
const Object& object = Object::Handle(isolate, Api::UnwrapHandle(handle));
|
2011-11-22 19:42:38 +00:00
|
|
|
uint8_t* data = NULL;
|
2012-08-27 20:25:44 +00:00
|
|
|
MessageWriter writer(&data, &allocator);
|
|
|
|
writer.WriteMessage(object);
|
|
|
|
intptr_t len = writer.BytesWritten();
|
2012-01-24 19:31:01 +00:00
|
|
|
return PortMap::PostMessage(new Message(
|
2012-08-27 20:25:44 +00:00
|
|
|
port_id, Message::kIllegalPort, data, len, Message::kNormalPriority));
|
2011-11-29 21:55:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-02-01 18:53:40 +00:00
|
|
|
DART_EXPORT Dart_Port Dart_NewNativePort(const char* name,
|
|
|
|
Dart_NativeMessageHandler handler,
|
|
|
|
bool handle_concurrently) {
|
|
|
|
if (name == NULL) {
|
|
|
|
name = "<UnnamedNativePort>";
|
|
|
|
}
|
|
|
|
if (handler == NULL) {
|
2012-04-19 19:47:27 +00:00
|
|
|
OS::PrintErr("%s expects argument 'handler' to be non-null.\n",
|
|
|
|
CURRENT_FUNC);
|
2012-08-01 18:47:33 +00:00
|
|
|
return ILLEGAL_PORT;
|
2012-02-01 18:53:40 +00:00
|
|
|
}
|
|
|
|
// Start the native port without a current isolate.
|
|
|
|
IsolateSaver saver(Isolate::Current());
|
|
|
|
Isolate::SetCurrent(NULL);
|
|
|
|
|
|
|
|
NativeMessageHandler* nmh = new NativeMessageHandler(name, handler);
|
|
|
|
Dart_Port port_id = PortMap::CreatePort(nmh);
|
2012-05-10 18:06:00 +00:00
|
|
|
nmh->Run(Dart::thread_pool(), NULL, NULL, 0);
|
2012-02-01 18:53:40 +00:00
|
|
|
return port_id;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT bool Dart_CloseNativePort(Dart_Port native_port_id) {
|
|
|
|
// Close the native port without a current isolate.
|
|
|
|
IsolateSaver saver(Isolate::Current());
|
|
|
|
Isolate::SetCurrent(NULL);
|
|
|
|
|
|
|
|
// TODO(turnidge): Check that the port is native before trying to close.
|
|
|
|
return PortMap::ClosePort(native_port_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-29 21:55:13 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_NewSendPort(Dart_Port port_id) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
2012-04-06 17:05:50 +00:00
|
|
|
return Api::NewHandle(isolate, DartLibraryCalls::NewSendPort(port_id));
|
2011-11-29 21:55:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_GetReceivePort(Dart_Port port_id) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
2012-04-04 20:31:49 +00:00
|
|
|
Library& isolate_lib = Library::Handle(isolate, Library::IsolateLibrary());
|
2012-02-27 22:50:44 +00:00
|
|
|
ASSERT(!isolate_lib.IsNull());
|
2012-03-07 21:15:58 +00:00
|
|
|
const String& public_class_name =
|
2012-04-04 20:31:49 +00:00
|
|
|
String::Handle(isolate, String::New("_ReceivePortImpl"));
|
2011-11-29 21:55:13 +00:00
|
|
|
const String& class_name =
|
2012-04-04 20:31:49 +00:00
|
|
|
String::Handle(isolate, isolate_lib.PrivateName(public_class_name));
|
2011-11-29 21:55:13 +00:00
|
|
|
const String& function_name =
|
2012-07-24 00:01:50 +00:00
|
|
|
String::Handle(isolate, Symbols::New("_get_or_create"));
|
2011-11-29 21:55:13 +00:00
|
|
|
const int kNumArguments = 1;
|
2012-04-04 20:31:49 +00:00
|
|
|
const Array& kNoArgumentNames = Array::Handle(isolate);
|
2011-11-29 21:55:13 +00:00
|
|
|
const Function& function = Function::Handle(
|
2012-04-04 20:31:49 +00:00
|
|
|
isolate,
|
2012-02-27 22:50:44 +00:00
|
|
|
Resolver::ResolveStatic(isolate_lib,
|
2011-11-29 21:55:13 +00:00
|
|
|
class_name,
|
|
|
|
function_name,
|
|
|
|
kNumArguments,
|
|
|
|
kNoArgumentNames,
|
|
|
|
Resolver::kIsQualified));
|
|
|
|
GrowableArray<const Object*> arguments(kNumArguments);
|
2012-04-04 20:31:49 +00:00
|
|
|
arguments.Add(&Integer::Handle(isolate, Integer::New(port_id)));
|
2012-04-06 17:05:50 +00:00
|
|
|
return Api::NewHandle(
|
2012-04-04 20:31:49 +00:00
|
|
|
isolate, DartEntry::InvokeStatic(function, arguments, kNoArgumentNames));
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-29 21:55:13 +00:00
|
|
|
DART_EXPORT Dart_Port Dart_GetMainPortId() {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
2011-12-01 19:17:10 +00:00
|
|
|
CHECK_ISOLATE(isolate);
|
2011-11-29 21:55:13 +00:00
|
|
|
return isolate->main_port();
|
|
|
|
}
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
// --- Scopes ----
|
2011-10-05 05:20:07 +00:00
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
DART_EXPORT void Dart_EnterScope() {
|
2011-11-12 05:55:22 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
2011-12-01 19:17:10 +00:00
|
|
|
CHECK_ISOLATE(isolate);
|
2011-11-22 19:42:38 +00:00
|
|
|
ApiState* state = isolate->api_state();
|
|
|
|
ASSERT(state != NULL);
|
|
|
|
ApiLocalScope* new_scope = new ApiLocalScope(state->top_scope(),
|
|
|
|
reinterpret_cast<uword>(&state));
|
|
|
|
ASSERT(new_scope != NULL);
|
|
|
|
state->set_top_scope(new_scope); // New scope is now the top scope.
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
DART_EXPORT void Dart_ExitScope() {
|
2011-11-12 05:55:22 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
2011-12-01 19:17:10 +00:00
|
|
|
CHECK_ISOLATE_SCOPE(isolate);
|
2011-11-22 19:42:38 +00:00
|
|
|
ApiState* state = isolate->api_state();
|
|
|
|
ApiLocalScope* scope = state->top_scope();
|
2011-12-01 19:17:10 +00:00
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
state->set_top_scope(scope->previous()); // Reset top scope to previous.
|
|
|
|
delete scope; // Free up the old scope which we have just exited.
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-02-17 07:43:24 +00:00
|
|
|
DART_EXPORT uint8_t* Dart_ScopeAllocate(intptr_t size) {
|
2012-10-16 22:05:40 +00:00
|
|
|
Zone* zone;
|
2012-02-17 07:43:24 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
if (isolate != NULL) {
|
|
|
|
ApiState* state = isolate->api_state();
|
|
|
|
if (state == NULL) return NULL;
|
|
|
|
ApiLocalScope* scope = state->top_scope();
|
|
|
|
zone = scope->zone();
|
|
|
|
} else {
|
|
|
|
ApiNativeScope* scope = ApiNativeScope::Current();
|
|
|
|
if (scope == NULL) return NULL;
|
|
|
|
zone = scope->zone();
|
|
|
|
}
|
2012-08-03 21:51:44 +00:00
|
|
|
return reinterpret_cast<uint8_t*>(zone->AllocUnsafe(size));
|
2012-02-17 07:43:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
// --- Objects ----
|
2011-10-05 05:20:07 +00:00
|
|
|
|
|
|
|
|
2011-11-05 00:09:36 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_Null() {
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
CHECK_ISOLATE_SCOPE(isolate);
|
|
|
|
return Api::Null(isolate);
|
2011-11-05 00:09:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-10-05 05:20:07 +00:00
|
|
|
DART_EXPORT bool Dart_IsNull(Dart_Handle object) {
|
2012-08-08 19:46:23 +00:00
|
|
|
return Api::ClassId(object) == kNullCid;
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-08 19:18:22 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_ObjectEquals(Dart_Handle obj1, Dart_Handle obj2,
|
|
|
|
bool* value) {
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
const Instance& expected =
|
|
|
|
Instance::CheckedHandle(isolate, Api::UnwrapHandle(obj1));
|
|
|
|
const Instance& actual =
|
|
|
|
Instance::CheckedHandle(isolate, Api::UnwrapHandle(obj2));
|
2012-02-02 19:05:06 +00:00
|
|
|
const Object& result =
|
2012-04-04 20:31:49 +00:00
|
|
|
Object::Handle(isolate, DartLibraryCalls::Equals(expected, actual));
|
2011-10-05 05:20:07 +00:00
|
|
|
if (result.IsBool()) {
|
2012-07-02 21:42:53 +00:00
|
|
|
*value = Bool::Cast(result).value();
|
2012-04-04 20:31:49 +00:00
|
|
|
return Api::Success(isolate);
|
2012-01-10 21:42:21 +00:00
|
|
|
} else if (result.IsError()) {
|
2012-04-06 17:05:50 +00:00
|
|
|
return Api::NewHandle(isolate, result.raw());
|
2011-10-05 05:20:07 +00:00
|
|
|
} else {
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("Expected boolean result from ==");
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// TODO(iposva): This call actually implements IsInstanceOfClass.
|
|
|
|
// Do we also need a real Dart_IsInstanceOf, which should take an instance
|
|
|
|
// rather than an object and a type rather than a class?
|
2011-11-08 19:18:22 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_ObjectIsType(Dart_Handle object,
|
2011-10-26 20:38:41 +00:00
|
|
|
Dart_Handle clazz,
|
|
|
|
bool* value) {
|
2011-11-12 05:55:22 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
2012-04-23 17:36:05 +00:00
|
|
|
|
|
|
|
const Class& cls = Api::UnwrapClassHandle(isolate, clazz);
|
2011-10-05 05:20:07 +00:00
|
|
|
if (cls.IsNull()) {
|
2012-04-23 17:36:05 +00:00
|
|
|
RETURN_TYPE_ERROR(isolate, clazz, Class);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
2012-04-04 20:31:49 +00:00
|
|
|
const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(object));
|
2012-04-23 17:36:05 +00:00
|
|
|
if (obj.IsError()) {
|
|
|
|
return object;
|
|
|
|
} else if (!obj.IsNull() && !obj.IsInstance()) {
|
|
|
|
return Api::NewError(
|
|
|
|
"%s expects argument 'object' to be an instance of Object.",
|
|
|
|
CURRENT_FUNC);
|
|
|
|
}
|
2011-10-05 05:20:07 +00:00
|
|
|
// Finalize all classes.
|
2011-11-12 05:55:22 +00:00
|
|
|
const char* msg = CheckIsolateState(isolate);
|
2011-10-05 05:20:07 +00:00
|
|
|
if (msg != NULL) {
|
2012-09-06 00:58:25 +00:00
|
|
|
return Api::NewError("%s", msg);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
2012-07-02 21:42:53 +00:00
|
|
|
if (obj.IsInstance()) {
|
|
|
|
const Type& type = Type::Handle(isolate,
|
|
|
|
Type::NewNonParameterizedType(cls));
|
|
|
|
Error& malformed_type_error = Error::Handle(isolate);
|
|
|
|
*value = Instance::Cast(obj).IsInstanceOf(type,
|
|
|
|
TypeArguments::Handle(isolate),
|
|
|
|
&malformed_type_error);
|
|
|
|
ASSERT(malformed_type_error.IsNull()); // Type was created from a class.
|
|
|
|
} else {
|
|
|
|
*value = false;
|
|
|
|
}
|
2012-04-04 20:31:49 +00:00
|
|
|
return Api::Success(isolate);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-06-12 21:07:49 +00:00
|
|
|
// --- Instances ----
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT bool Dart_IsInstance(Dart_Handle object) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(object));
|
|
|
|
return obj.IsInstance();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// TODO(turnidge): Technically, null has a class. Should we allow it?
|
|
|
|
DART_EXPORT Dart_Handle Dart_InstanceGetClass(Dart_Handle instance) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
const Instance& obj = Api::UnwrapInstanceHandle(isolate, instance);
|
|
|
|
if (obj.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, instance, Instance);
|
|
|
|
}
|
|
|
|
return Api::NewHandle(isolate, obj.clazz());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
// --- Numbers ----
|
|
|
|
|
|
|
|
|
2011-10-05 05:20:07 +00:00
|
|
|
DART_EXPORT bool Dart_IsNumber(Dart_Handle object) {
|
2012-05-31 12:41:37 +00:00
|
|
|
return RawObject::IsNumberClassId(Api::ClassId(object));
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
// --- Integers ----
|
|
|
|
|
|
|
|
|
2011-10-05 05:20:07 +00:00
|
|
|
DART_EXPORT bool Dart_IsInteger(Dart_Handle object) {
|
2012-05-31 12:41:37 +00:00
|
|
|
return RawObject::IsIntegerClassId(Api::ClassId(object));
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_IntegerFitsIntoInt64(Dart_Handle integer,
|
|
|
|
bool* fits) {
|
2012-05-14 17:58:59 +00:00
|
|
|
// Fast path for Smis and Mints.
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
2012-04-16 20:30:37 +00:00
|
|
|
CHECK_ISOLATE(isolate);
|
2012-06-04 10:29:00 +00:00
|
|
|
intptr_t class_id = Api::ClassId(integer);
|
2012-08-08 19:46:23 +00:00
|
|
|
if (class_id == kSmiCid || class_id == kMintCid) {
|
2012-04-16 20:30:37 +00:00
|
|
|
*fits = true;
|
|
|
|
return Api::Success(isolate);
|
|
|
|
}
|
2012-09-19 01:11:37 +00:00
|
|
|
// Slow path for Mints and Bigints.
|
2012-04-16 20:30:37 +00:00
|
|
|
DARTSCOPE_NOCHECKS(isolate);
|
2012-04-04 20:31:49 +00:00
|
|
|
const Integer& int_obj = Api::UnwrapIntegerHandle(isolate, integer);
|
2011-12-09 17:25:44 +00:00
|
|
|
if (int_obj.IsNull()) {
|
2012-04-04 20:31:49 +00:00
|
|
|
RETURN_TYPE_ERROR(isolate, integer, Integer);
|
2011-12-09 17:25:44 +00:00
|
|
|
}
|
2012-07-02 21:42:53 +00:00
|
|
|
ASSERT(!BigintOperations::FitsIntoMint(Bigint::Cast(int_obj)));
|
2012-05-14 17:58:59 +00:00
|
|
|
*fits = false;
|
2012-04-04 20:31:49 +00:00
|
|
|
return Api::Success(isolate);
|
2011-12-09 17:25:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_IntegerFitsIntoUint64(Dart_Handle integer,
|
|
|
|
bool* fits) {
|
2012-04-16 20:30:37 +00:00
|
|
|
// Fast path for Smis.
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
2012-04-16 20:30:37 +00:00
|
|
|
CHECK_ISOLATE(isolate);
|
|
|
|
if (Api::IsSmi(integer)) {
|
|
|
|
*fits = (Api::SmiValue(integer) >= 0);
|
|
|
|
return Api::Success(isolate);
|
|
|
|
}
|
2012-09-19 01:11:37 +00:00
|
|
|
// Slow path for Mints and Bigints.
|
2012-04-16 20:30:37 +00:00
|
|
|
DARTSCOPE_NOCHECKS(isolate);
|
2012-04-04 20:31:49 +00:00
|
|
|
const Integer& int_obj = Api::UnwrapIntegerHandle(isolate, integer);
|
2011-12-09 17:25:44 +00:00
|
|
|
if (int_obj.IsNull()) {
|
2012-04-04 20:31:49 +00:00
|
|
|
RETURN_TYPE_ERROR(isolate, integer, Integer);
|
2011-12-09 17:25:44 +00:00
|
|
|
}
|
2012-09-19 01:11:37 +00:00
|
|
|
ASSERT(!int_obj.IsSmi());
|
|
|
|
if (int_obj.IsMint()) {
|
2011-12-09 17:25:44 +00:00
|
|
|
*fits = !int_obj.IsNegative();
|
|
|
|
} else {
|
2012-07-02 21:42:53 +00:00
|
|
|
*fits = BigintOperations::FitsIntoUint64(Bigint::Cast(int_obj));
|
2011-12-09 17:25:44 +00:00
|
|
|
}
|
2012-04-04 20:31:49 +00:00
|
|
|
return Api::Success(isolate);
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-10-05 05:20:07 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_NewInteger(int64_t value) {
|
2012-04-16 20:30:37 +00:00
|
|
|
// Fast path for Smis.
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
2012-04-16 20:30:37 +00:00
|
|
|
CHECK_ISOLATE(isolate);
|
|
|
|
if (Smi::IsValid64(value)) {
|
|
|
|
NOHANDLESCOPE(isolate);
|
2012-09-19 01:11:37 +00:00
|
|
|
return Api::NewHandle(isolate, Smi::New(static_cast<intptr_t>(value)));
|
2012-04-16 20:30:37 +00:00
|
|
|
}
|
2012-09-19 01:11:37 +00:00
|
|
|
// Slow path for Mints and Bigints.
|
2012-04-16 20:30:37 +00:00
|
|
|
DARTSCOPE_NOCHECKS(isolate);
|
2012-04-06 17:05:50 +00:00
|
|
|
return Api::NewHandle(isolate, Integer::New(value));
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_NewIntegerFromHexCString(const char* str) {
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
const String& str_obj = String::Handle(isolate, String::New(str));
|
2012-04-06 17:05:50 +00:00
|
|
|
return Api::NewHandle(isolate, Integer::New(str_obj));
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-12-09 17:25:44 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_IntegerToInt64(Dart_Handle integer,
|
|
|
|
int64_t* value) {
|
2012-04-16 20:30:37 +00:00
|
|
|
// Fast path for Smis.
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
2012-04-16 20:30:37 +00:00
|
|
|
CHECK_ISOLATE(isolate);
|
|
|
|
if (Api::IsSmi(integer)) {
|
|
|
|
*value = Api::SmiValue(integer);
|
|
|
|
return Api::Success(isolate);
|
|
|
|
}
|
2012-09-19 01:11:37 +00:00
|
|
|
// Slow path for Mints and Bigints.
|
2012-04-16 20:30:37 +00:00
|
|
|
DARTSCOPE_NOCHECKS(isolate);
|
2012-04-04 20:31:49 +00:00
|
|
|
const Integer& int_obj = Api::UnwrapIntegerHandle(isolate, integer);
|
2011-12-09 17:25:44 +00:00
|
|
|
if (int_obj.IsNull()) {
|
2012-04-04 20:31:49 +00:00
|
|
|
RETURN_TYPE_ERROR(isolate, integer, Integer);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
2012-09-19 01:11:37 +00:00
|
|
|
ASSERT(!int_obj.IsSmi());
|
|
|
|
if (int_obj.IsMint()) {
|
2011-12-09 17:25:44 +00:00
|
|
|
*value = int_obj.AsInt64Value();
|
2012-04-04 20:31:49 +00:00
|
|
|
return Api::Success(isolate);
|
2011-12-09 17:25:44 +00:00
|
|
|
} else {
|
2012-07-02 21:42:53 +00:00
|
|
|
const Bigint& bigint = Bigint::Cast(int_obj);
|
2012-02-28 18:36:39 +00:00
|
|
|
if (BigintOperations::FitsIntoMint(bigint)) {
|
|
|
|
*value = BigintOperations::ToMint(bigint);
|
2012-04-04 20:31:49 +00:00
|
|
|
return Api::Success(isolate);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
}
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("%s: Integer %s cannot be represented as an int64_t.",
|
|
|
|
CURRENT_FUNC, int_obj.ToCString());
|
2011-10-26 20:38:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-12-09 17:25:44 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_IntegerToUint64(Dart_Handle integer,
|
|
|
|
uint64_t* value) {
|
2012-04-16 20:30:37 +00:00
|
|
|
// Fast path for Smis.
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
2012-04-16 20:30:37 +00:00
|
|
|
CHECK_ISOLATE(isolate);
|
|
|
|
if (Api::IsSmi(integer)) {
|
|
|
|
intptr_t smi_value = Api::SmiValue(integer);
|
|
|
|
if (smi_value >= 0) {
|
|
|
|
*value = smi_value;
|
|
|
|
return Api::Success(isolate);
|
|
|
|
}
|
|
|
|
}
|
2012-09-19 01:11:37 +00:00
|
|
|
// Slow path for Mints and Bigints.
|
2012-04-16 20:30:37 +00:00
|
|
|
DARTSCOPE_NOCHECKS(isolate);
|
2012-04-04 20:31:49 +00:00
|
|
|
const Integer& int_obj = Api::UnwrapIntegerHandle(isolate, integer);
|
2011-12-09 17:25:44 +00:00
|
|
|
if (int_obj.IsNull()) {
|
2012-04-04 20:31:49 +00:00
|
|
|
RETURN_TYPE_ERROR(isolate, integer, Integer);
|
2011-12-09 17:25:44 +00:00
|
|
|
}
|
2012-09-19 01:11:37 +00:00
|
|
|
ASSERT(!int_obj.IsSmi());
|
|
|
|
if (int_obj.IsMint() && !int_obj.IsNegative()) {
|
|
|
|
*value = int_obj.AsInt64Value();
|
|
|
|
return Api::Success(isolate);
|
2011-12-09 17:25:44 +00:00
|
|
|
} else {
|
2012-07-02 21:42:53 +00:00
|
|
|
const Bigint& bigint = Bigint::Cast(int_obj);
|
2011-12-09 17:25:44 +00:00
|
|
|
if (BigintOperations::FitsIntoUint64(bigint)) {
|
|
|
|
*value = BigintOperations::ToUint64(bigint);
|
2012-04-04 20:31:49 +00:00
|
|
|
return Api::Success(isolate);
|
2011-12-09 17:25:44 +00:00
|
|
|
}
|
|
|
|
}
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("%s: Integer %s cannot be represented as a uint64_t.",
|
|
|
|
CURRENT_FUNC, int_obj.ToCString());
|
2011-12-09 17:25:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-08-03 21:51:44 +00:00
|
|
|
static uword BigintAllocate(intptr_t size) {
|
|
|
|
return Api::TopScope(Isolate::Current())->zone()->AllocUnsafe(size);
|
2012-04-04 20:31:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-12-09 17:25:44 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_IntegerToHexCString(Dart_Handle integer,
|
|
|
|
const char** value) {
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
const Integer& int_obj = Api::UnwrapIntegerHandle(isolate, integer);
|
2011-12-09 17:25:44 +00:00
|
|
|
if (int_obj.IsNull()) {
|
2012-04-04 20:31:49 +00:00
|
|
|
RETURN_TYPE_ERROR(isolate, integer, Integer);
|
2011-12-09 17:25:44 +00:00
|
|
|
}
|
|
|
|
if (int_obj.IsSmi() || int_obj.IsMint()) {
|
2012-07-02 21:42:53 +00:00
|
|
|
const Bigint& bigint = Bigint::Handle(isolate,
|
|
|
|
BigintOperations::NewFromInt64(int_obj.AsInt64Value()));
|
2012-08-03 21:51:44 +00:00
|
|
|
*value = BigintOperations::ToHexCString(bigint, BigintAllocate);
|
2011-12-09 17:25:44 +00:00
|
|
|
} else {
|
2012-08-03 21:51:44 +00:00
|
|
|
*value = BigintOperations::ToHexCString(Bigint::Cast(int_obj),
|
|
|
|
BigintAllocate);
|
2011-10-26 20:38:41 +00:00
|
|
|
}
|
2012-04-04 20:31:49 +00:00
|
|
|
return Api::Success(isolate);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
// --- Booleans ----
|
2011-10-05 05:20:07 +00:00
|
|
|
|
|
|
|
|
2011-11-05 00:09:36 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_True() {
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
CHECK_ISOLATE_SCOPE(isolate);
|
|
|
|
return Api::True(isolate);
|
2011-11-05 00:09:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_False() {
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
CHECK_ISOLATE_SCOPE(isolate);
|
|
|
|
return Api::False(isolate);
|
2011-11-05 00:09:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-10-05 05:20:07 +00:00
|
|
|
DART_EXPORT bool Dart_IsBoolean(Dart_Handle object) {
|
2012-08-08 19:46:23 +00:00
|
|
|
return Api::ClassId(object) == kBoolCid;
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_NewBoolean(bool value) {
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
CHECK_ISOLATE_SCOPE(isolate);
|
|
|
|
return value ? Api::True(isolate) : Api::False(isolate);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-12-08 23:50:40 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_BooleanValue(Dart_Handle boolean_obj,
|
2011-10-26 20:38:41 +00:00
|
|
|
bool* value) {
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
const Bool& obj = Api::UnwrapBoolHandle(isolate, boolean_obj);
|
2011-12-08 23:50:40 +00:00
|
|
|
if (obj.IsNull()) {
|
2012-04-04 20:31:49 +00:00
|
|
|
RETURN_TYPE_ERROR(isolate, boolean_obj, Bool);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
2011-12-08 23:50:40 +00:00
|
|
|
*value = obj.value();
|
2012-04-04 20:31:49 +00:00
|
|
|
return Api::Success(isolate);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
// --- Doubles ---
|
|
|
|
|
|
|
|
|
2011-10-05 05:20:07 +00:00
|
|
|
DART_EXPORT bool Dart_IsDouble(Dart_Handle object) {
|
2012-08-08 19:46:23 +00:00
|
|
|
return Api::ClassId(object) == kDoubleCid;
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_NewDouble(double value) {
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
2012-04-06 17:05:50 +00:00
|
|
|
return Api::NewHandle(isolate, Double::New(value));
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-12-08 23:50:40 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_DoubleValue(Dart_Handle double_obj,
|
|
|
|
double* value) {
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
const Double& obj = Api::UnwrapDoubleHandle(isolate, double_obj);
|
2011-12-08 23:50:40 +00:00
|
|
|
if (obj.IsNull()) {
|
2012-04-04 20:31:49 +00:00
|
|
|
RETURN_TYPE_ERROR(isolate, double_obj, Double);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
2011-12-08 23:50:40 +00:00
|
|
|
*value = obj.value();
|
2012-04-04 20:31:49 +00:00
|
|
|
return Api::Success(isolate);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
// --- Strings ---
|
|
|
|
|
|
|
|
|
2011-10-05 05:20:07 +00:00
|
|
|
DART_EXPORT bool Dart_IsString(Dart_Handle object) {
|
2012-05-31 12:41:37 +00:00
|
|
|
return RawObject::IsStringClassId(Api::ClassId(object));
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-11-16 00:13:18 +00:00
|
|
|
DART_EXPORT bool Dart_IsStringLatin1(Dart_Handle object) {
|
2012-05-31 12:41:37 +00:00
|
|
|
return RawObject::IsOneByteStringClassId(Api::ClassId(object));
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-10-26 20:38:41 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_StringLength(Dart_Handle str, intptr_t* len) {
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
2012-05-21 21:41:49 +00:00
|
|
|
const String& str_obj = Api::UnwrapStringHandle(isolate, str);
|
|
|
|
if (str_obj.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, str, String);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
2012-05-21 21:41:49 +00:00
|
|
|
*len = str_obj.Length();
|
|
|
|
return Api::Success(isolate);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-10-31 17:56:46 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_NewStringFromCString(const char* str) {
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
2012-06-20 22:09:20 +00:00
|
|
|
if (str == NULL) {
|
2012-07-09 23:57:08 +00:00
|
|
|
RETURN_NULL_ERROR(str);
|
2012-06-20 22:09:20 +00:00
|
|
|
}
|
2012-04-06 17:05:50 +00:00
|
|
|
return Api::NewHandle(isolate, String::New(str));
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-10-31 17:56:46 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_NewStringFromUTF8(const uint8_t* utf8_array,
|
|
|
|
intptr_t length) {
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
2012-10-31 17:56:46 +00:00
|
|
|
if (utf8_array == NULL && length != 0) {
|
|
|
|
RETURN_NULL_ERROR(utf8_array);
|
2012-08-01 18:22:30 +00:00
|
|
|
}
|
|
|
|
CHECK_LENGTH(length, String::kMaxElements);
|
2012-10-31 17:56:46 +00:00
|
|
|
if (!Utf8::IsValid(utf8_array, length)) {
|
|
|
|
return Api::NewError("%s expects argument 'str' to be valid UTF-8.",
|
|
|
|
CURRENT_FUNC);
|
|
|
|
}
|
2012-12-04 22:18:12 +00:00
|
|
|
return Api::NewHandle(isolate, String::FromUTF8(utf8_array, length));
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-10-31 17:56:46 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_NewStringFromUTF16(const uint16_t* utf16_array,
|
|
|
|
intptr_t length) {
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
2012-10-31 17:56:46 +00:00
|
|
|
if (utf16_array == NULL && length != 0) {
|
|
|
|
RETURN_NULL_ERROR(utf16_array);
|
2012-08-01 18:22:30 +00:00
|
|
|
}
|
|
|
|
CHECK_LENGTH(length, String::kMaxElements);
|
2012-12-05 23:37:37 +00:00
|
|
|
return Api::NewHandle(isolate, String::FromUTF16(utf16_array, length));
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-11-21 00:30:27 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_NewStringFromUTF32(const int32_t* utf32_array,
|
2012-10-31 17:56:46 +00:00
|
|
|
intptr_t length) {
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
2012-10-31 17:56:46 +00:00
|
|
|
if (utf32_array == NULL && length != 0) {
|
|
|
|
RETURN_NULL_ERROR(utf32_array);
|
2012-08-01 18:22:30 +00:00
|
|
|
}
|
|
|
|
CHECK_LENGTH(length, String::kMaxElements);
|
2012-12-05 23:37:37 +00:00
|
|
|
return Api::NewHandle(isolate, String::FromUTF32(utf32_array, length));
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-12-05 17:55:01 +00:00
|
|
|
DART_EXPORT bool Dart_IsExternalString(Dart_Handle object) {
|
2012-05-31 12:41:37 +00:00
|
|
|
return RawObject::IsExternalStringClassId(Api::ClassId(object));
|
2011-12-05 17:55:01 +00:00
|
|
|
}
|
|
|
|
|
2012-08-28 21:18:21 +00:00
|
|
|
|
2011-12-05 17:55:01 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_ExternalStringGetPeer(Dart_Handle object,
|
|
|
|
void** peer) {
|
|
|
|
if (peer == NULL) {
|
2012-07-09 23:57:08 +00:00
|
|
|
RETURN_NULL_ERROR(peer);
|
2012-08-29 20:04:55 +00:00
|
|
|
}
|
|
|
|
|
2012-08-30 00:17:52 +00:00
|
|
|
if (Api::ExternalStringGetPeerHelper(object, peer)) {
|
2012-08-29 20:04:55 +00:00
|
|
|
return Api::Success(Isolate::Current());
|
2012-08-29 18:06:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// It's not an external string, return appropriate error.
|
2012-08-29 20:04:55 +00:00
|
|
|
if (!RawObject::IsStringClassId(Api::ClassId(object))) {
|
2012-08-29 18:06:17 +00:00
|
|
|
RETURN_TYPE_ERROR(Isolate::Current(), object, String);
|
|
|
|
} else {
|
|
|
|
return
|
|
|
|
Api::NewError(
|
|
|
|
"%s expects argument 'object' to be an external String.",
|
|
|
|
CURRENT_FUNC);
|
2011-12-05 17:55:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-11-29 23:43:47 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_NewExternalLatin1String(
|
|
|
|
const uint8_t* latin1_array,
|
|
|
|
intptr_t length,
|
|
|
|
void* peer,
|
|
|
|
Dart_PeerFinalizer cback) {
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
2012-11-29 23:43:47 +00:00
|
|
|
if (latin1_array == NULL && length != 0) {
|
|
|
|
RETURN_NULL_ERROR(latin1_array);
|
2012-02-11 04:34:44 +00:00
|
|
|
}
|
2012-08-01 18:22:30 +00:00
|
|
|
CHECK_LENGTH(length, String::kMaxElements);
|
2012-10-31 17:56:46 +00:00
|
|
|
return Api::NewHandle(isolate,
|
2012-11-29 23:43:47 +00:00
|
|
|
String::NewExternal(latin1_array, length, peer, cback));
|
2011-11-19 00:33:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-10-31 17:56:46 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_NewExternalUTF16String(const uint16_t* utf16_array,
|
|
|
|
intptr_t length,
|
|
|
|
void* peer,
|
|
|
|
Dart_PeerFinalizer cback) {
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
2012-10-31 17:56:46 +00:00
|
|
|
if (utf16_array == NULL && length != 0) {
|
|
|
|
RETURN_NULL_ERROR(utf16_array);
|
2012-02-11 04:34:44 +00:00
|
|
|
}
|
2012-08-01 18:22:30 +00:00
|
|
|
CHECK_LENGTH(length, String::kMaxElements);
|
2012-10-31 17:56:46 +00:00
|
|
|
return Api::NewHandle(isolate,
|
|
|
|
String::NewExternal(utf16_array, length, peer, cback));
|
2011-11-19 00:33:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-10-31 17:56:46 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_StringToCString(Dart_Handle object,
|
|
|
|
const char** cstr) {
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
2012-11-06 19:07:43 +00:00
|
|
|
if (cstr == NULL) {
|
|
|
|
RETURN_NULL_ERROR(cstr);
|
|
|
|
}
|
2012-10-31 17:56:46 +00:00
|
|
|
const String& str_obj = Api::UnwrapStringHandle(isolate, object);
|
2012-05-21 21:41:49 +00:00
|
|
|
if (str_obj.IsNull()) {
|
2012-10-31 17:56:46 +00:00
|
|
|
RETURN_TYPE_ERROR(isolate, object, String);
|
2012-05-21 21:41:49 +00:00
|
|
|
}
|
2012-10-31 17:56:46 +00:00
|
|
|
intptr_t string_length = Utf8::Length(str_obj);
|
|
|
|
char* res = Api::TopScope(isolate)->zone()->Alloc<char>(string_length + 1);
|
|
|
|
if (res == NULL) {
|
|
|
|
return Api::NewError("Unable to allocate memory");
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
2012-10-31 17:56:46 +00:00
|
|
|
const char* string_value = str_obj.ToCString();
|
|
|
|
memmove(res, string_value, string_length + 1);
|
|
|
|
ASSERT(res[string_length] == '\0');
|
|
|
|
*cstr = res;
|
2012-05-21 21:41:49 +00:00
|
|
|
return Api::Success(isolate);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-10-31 17:56:46 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_StringToUTF8(Dart_Handle str,
|
2012-11-06 19:07:43 +00:00
|
|
|
uint8_t** utf8_array,
|
2012-10-31 17:56:46 +00:00
|
|
|
intptr_t* length) {
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
2012-11-06 19:07:43 +00:00
|
|
|
if (utf8_array == NULL) {
|
|
|
|
RETURN_NULL_ERROR(utf8_array);
|
|
|
|
}
|
|
|
|
if (length == NULL) {
|
|
|
|
RETURN_NULL_ERROR(length);
|
|
|
|
}
|
2012-05-21 21:41:49 +00:00
|
|
|
const String& str_obj = Api::UnwrapStringHandle(isolate, str);
|
|
|
|
if (str_obj.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, str, String);
|
|
|
|
}
|
2012-11-06 19:07:43 +00:00
|
|
|
intptr_t str_len = Utf8::Length(str_obj);
|
|
|
|
*utf8_array = Api::TopScope(isolate)->zone()->Alloc<uint8_t>(str_len);
|
|
|
|
if (*utf8_array == NULL) {
|
|
|
|
return Api::NewError("Unable to allocate memory");
|
2012-05-21 21:41:49 +00:00
|
|
|
}
|
2012-11-06 19:07:43 +00:00
|
|
|
str_obj.ToUTF8(*utf8_array, str_len);
|
|
|
|
*length = str_len;
|
2012-05-21 21:41:49 +00:00
|
|
|
return Api::Success(isolate);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-10-31 17:56:46 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_StringToUTF16(Dart_Handle str,
|
|
|
|
uint16_t* utf16_array,
|
|
|
|
intptr_t* length) {
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
2012-05-21 21:41:49 +00:00
|
|
|
const String& str_obj = Api::UnwrapStringHandle(isolate, str);
|
|
|
|
if (str_obj.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, str, String);
|
|
|
|
}
|
|
|
|
intptr_t str_len = str_obj.Length();
|
|
|
|
intptr_t copy_len = (str_len > *length) ? *length : str_len;
|
|
|
|
for (intptr_t i = 0; i < copy_len; i++) {
|
2012-10-31 17:56:46 +00:00
|
|
|
utf16_array[i] = static_cast<uint16_t>(str_obj.CharAt(i));
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
2012-05-21 21:41:49 +00:00
|
|
|
*length = copy_len;
|
|
|
|
return Api::Success(isolate);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-11-15 21:37:26 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_StringStorageSize(Dart_Handle str,
|
|
|
|
intptr_t* size) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
const String& str_obj = Api::UnwrapStringHandle(isolate, str);
|
|
|
|
if (str_obj.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, str, String);
|
|
|
|
}
|
|
|
|
if (size == NULL) {
|
|
|
|
RETURN_NULL_ERROR(size);
|
|
|
|
}
|
|
|
|
*size = (str_obj.Length() * str_obj.CharSize());
|
|
|
|
return Api::Success(isolate);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_MakeExternalString(Dart_Handle str,
|
|
|
|
void* array,
|
|
|
|
intptr_t length,
|
|
|
|
void* peer,
|
|
|
|
Dart_PeerFinalizer cback) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
const String& str_obj = Api::UnwrapStringHandle(isolate, str);
|
|
|
|
if (str_obj.IsExternal()) {
|
|
|
|
return str; // String is already an external string.
|
|
|
|
}
|
|
|
|
if (str_obj.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, str, String);
|
|
|
|
}
|
|
|
|
if (array == NULL) {
|
|
|
|
RETURN_NULL_ERROR(array);
|
|
|
|
}
|
2012-11-29 23:19:17 +00:00
|
|
|
if (str_obj.IsCanonical()) {
|
|
|
|
return Api::NewError("Dart_MakeExternalString "
|
|
|
|
"cannot externalize a read-only string.");
|
|
|
|
}
|
2012-11-15 21:37:26 +00:00
|
|
|
intptr_t str_size = (str_obj.Length() * str_obj.CharSize());
|
|
|
|
if ((length < str_size) || (length > String::kMaxElements)) {
|
|
|
|
return Api::NewError("Dart_MakeExternalString "
|
|
|
|
"expects argument length to be in the range"
|
|
|
|
"[%"Pd"..%"Pd"].",
|
|
|
|
str_size, String::kMaxElements);
|
|
|
|
}
|
|
|
|
return Api::NewHandle(isolate,
|
|
|
|
str_obj.MakeExternal(array, length, peer, cback));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
// --- Lists ---
|
|
|
|
|
|
|
|
|
2011-10-31 21:08:39 +00:00
|
|
|
static RawInstance* GetListInstance(Isolate* isolate, const Object& obj) {
|
|
|
|
if (obj.IsInstance()) {
|
2012-07-02 21:42:53 +00:00
|
|
|
const Instance& instance = Instance::Cast(obj);
|
2012-11-16 01:31:15 +00:00
|
|
|
const Class& obj_class = Class::Handle(isolate, obj.clazz());
|
|
|
|
const Class& list_class =
|
|
|
|
Class::Handle(isolate, isolate->object_store()->list_class());
|
2012-04-04 20:31:49 +00:00
|
|
|
Error& malformed_type_error = Error::Handle(isolate);
|
2012-11-16 01:31:15 +00:00
|
|
|
if (obj_class.IsSubtypeOf(TypeArguments::Handle(isolate),
|
|
|
|
list_class,
|
2012-04-04 20:31:49 +00:00
|
|
|
TypeArguments::Handle(isolate),
|
2012-03-07 02:23:12 +00:00
|
|
|
&malformed_type_error)) {
|
|
|
|
ASSERT(malformed_type_error.IsNull()); // Type is a raw List.
|
2011-11-24 00:26:18 +00:00
|
|
|
return instance.raw();
|
|
|
|
}
|
2011-10-31 21:08:39 +00:00
|
|
|
}
|
|
|
|
return Instance::null();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-04 12:25:53 +00:00
|
|
|
DART_EXPORT bool Dart_IsList(Dart_Handle object) {
|
2012-05-31 12:41:37 +00:00
|
|
|
if (RawObject::IsBuiltinListClassId(Api::ClassId(object))) {
|
2012-05-14 17:58:59 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-11-12 05:55:22 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
2012-04-04 20:31:49 +00:00
|
|
|
const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(object));
|
2012-05-14 17:58:59 +00:00
|
|
|
return GetListInstance(isolate, obj) != Instance::null();
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-04 12:25:53 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_NewList(intptr_t length) {
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
2012-08-01 18:22:30 +00:00
|
|
|
CHECK_LENGTH(length, Array::kMaxElements);
|
2012-04-06 17:05:50 +00:00
|
|
|
return Api::NewHandle(isolate, Array::New(length));
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-04-09 21:50:53 +00:00
|
|
|
#define GET_LIST_LENGTH(isolate, type, obj, len) \
|
|
|
|
type& array = type::Handle(isolate); \
|
|
|
|
array ^= obj.raw(); \
|
|
|
|
*len = array.Length(); \
|
|
|
|
return Api::Success(isolate); \
|
|
|
|
|
|
|
|
|
2011-11-04 12:25:53 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_ListLength(Dart_Handle list, intptr_t* len) {
|
2011-11-12 05:55:22 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
2012-04-04 20:31:49 +00:00
|
|
|
const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(list));
|
2012-06-12 21:07:49 +00:00
|
|
|
if (obj.IsError()) {
|
|
|
|
// Pass through errors.
|
|
|
|
return list;
|
|
|
|
}
|
2012-02-01 21:48:27 +00:00
|
|
|
if (obj.IsByteArray()) {
|
2012-04-09 21:50:53 +00:00
|
|
|
GET_LIST_LENGTH(isolate, ByteArray, obj, len);
|
2012-02-01 21:48:27 +00:00
|
|
|
}
|
2011-10-05 05:20:07 +00:00
|
|
|
if (obj.IsArray()) {
|
2012-04-09 21:50:53 +00:00
|
|
|
GET_LIST_LENGTH(isolate, Array, obj, len);
|
|
|
|
}
|
|
|
|
if (obj.IsGrowableObjectArray()) {
|
|
|
|
GET_LIST_LENGTH(isolate, GrowableObjectArray, obj, len);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
2011-10-31 21:08:39 +00:00
|
|
|
// Now check and handle a dart object that implements the List interface.
|
2012-04-04 20:31:49 +00:00
|
|
|
const Instance& instance =
|
|
|
|
Instance::Handle(isolate, GetListInstance(isolate, obj));
|
2012-02-02 19:05:06 +00:00
|
|
|
if (instance.IsNull()) {
|
2012-06-12 21:07:49 +00:00
|
|
|
return Api::NewError("Object does not implement the List interface");
|
2012-02-02 19:05:06 +00:00
|
|
|
}
|
2012-12-01 00:34:19 +00:00
|
|
|
String& name = String::Handle(isolate, Symbols::Length());
|
2012-02-02 19:05:06 +00:00
|
|
|
name = Field::GetterName(name);
|
2012-04-04 20:31:49 +00:00
|
|
|
const Function& function =
|
|
|
|
Function::Handle(isolate, Resolver::ResolveDynamic(instance, name, 1, 0));
|
2012-02-02 19:05:06 +00:00
|
|
|
if (function.IsNull()) {
|
|
|
|
return Api::NewError("List object does not have a 'length' field.");
|
2011-10-31 21:08:39 +00:00
|
|
|
}
|
|
|
|
|
2012-02-02 19:05:06 +00:00
|
|
|
GrowableArray<const Object*> args(0);
|
2012-04-04 20:31:49 +00:00
|
|
|
const Array& kNoArgumentNames = Array::Handle(isolate);
|
2012-02-02 19:05:06 +00:00
|
|
|
const Object& retval = Object::Handle(
|
2012-04-04 20:31:49 +00:00
|
|
|
isolate,
|
2012-02-02 19:05:06 +00:00
|
|
|
DartEntry::InvokeDynamic(instance, function, args, kNoArgumentNames));
|
2012-09-19 01:11:37 +00:00
|
|
|
if (retval.IsSmi()) {
|
|
|
|
*len = Smi::Cast(retval).Value();
|
2012-04-04 20:31:49 +00:00
|
|
|
return Api::Success(isolate);
|
2012-09-19 01:11:37 +00:00
|
|
|
} else if (retval.IsMint() || retval.IsBigint()) {
|
|
|
|
if (retval.IsMint()) {
|
|
|
|
int64_t mint_value = Mint::Cast(retval).value();
|
|
|
|
if (mint_value >= kIntptrMin && mint_value <= kIntptrMax) {
|
|
|
|
*len = static_cast<intptr_t>(mint_value);
|
|
|
|
}
|
2011-10-31 21:08:39 +00:00
|
|
|
} else {
|
2012-09-19 01:11:37 +00:00
|
|
|
// Check for a non-canonical Mint range value.
|
|
|
|
ASSERT(retval.IsBigint());
|
|
|
|
const Bigint& bigint = Bigint::Handle();
|
|
|
|
if (BigintOperations::FitsIntoMint(bigint)) {
|
|
|
|
int64_t bigint_value = bigint.AsInt64Value();
|
|
|
|
if (bigint_value >= kIntptrMin && bigint_value <= kIntptrMax) {
|
|
|
|
*len = static_cast<intptr_t>(bigint_value);
|
|
|
|
}
|
|
|
|
}
|
2011-10-31 21:08:39 +00:00
|
|
|
}
|
2012-09-19 01:11:37 +00:00
|
|
|
return Api::NewError("Length of List object is greater than the "
|
|
|
|
"maximum value that 'len' parameter can hold");
|
2012-02-02 19:05:06 +00:00
|
|
|
} else if (retval.IsError()) {
|
2012-04-06 17:05:50 +00:00
|
|
|
return Api::NewHandle(isolate, retval.raw());
|
2012-02-02 19:05:06 +00:00
|
|
|
} else {
|
|
|
|
return Api::NewError("Length of List object is not an integer");
|
2011-10-31 21:08:39 +00:00
|
|
|
}
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-04-09 21:50:53 +00:00
|
|
|
#define GET_LIST_ELEMENT(isolate, type, obj, index) \
|
2012-07-02 21:42:53 +00:00
|
|
|
const type& array_obj = type::Cast(obj); \
|
2012-04-09 21:50:53 +00:00
|
|
|
if ((index >= 0) && (index < array_obj.Length())) { \
|
|
|
|
return Api::NewHandle(isolate, array_obj.At(index)); \
|
|
|
|
} \
|
|
|
|
return Api::NewError("Invalid index passed in to access list element"); \
|
|
|
|
|
|
|
|
|
2011-11-04 12:25:53 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_ListGetAt(Dart_Handle list, intptr_t index) {
|
2011-11-12 05:55:22 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
2012-04-04 20:31:49 +00:00
|
|
|
const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(list));
|
2011-10-05 05:20:07 +00:00
|
|
|
if (obj.IsArray()) {
|
2012-04-09 21:50:53 +00:00
|
|
|
GET_LIST_ELEMENT(isolate, Array, obj, index);
|
2012-08-22 13:42:06 +00:00
|
|
|
} else if (obj.IsGrowableObjectArray()) {
|
2012-04-09 21:50:53 +00:00
|
|
|
GET_LIST_ELEMENT(isolate, GrowableObjectArray, obj, index);
|
2012-08-22 13:42:06 +00:00
|
|
|
} else if (obj.IsError()) {
|
|
|
|
return list;
|
|
|
|
} else {
|
|
|
|
// Check and handle a dart object that implements the List interface.
|
|
|
|
const Instance& instance =
|
|
|
|
Instance::Handle(isolate, GetListInstance(isolate, obj));
|
|
|
|
if (!instance.IsNull()) {
|
2012-12-01 00:34:19 +00:00
|
|
|
String& name = String::Handle(isolate, Symbols::IndexToken());
|
2012-08-22 13:42:06 +00:00
|
|
|
const Function& function =
|
|
|
|
Function::Handle(isolate,
|
|
|
|
Resolver::ResolveDynamic(instance, name, 2, 0));
|
|
|
|
if (!function.IsNull()) {
|
|
|
|
GrowableArray<const Object*> args(1);
|
|
|
|
Integer& indexobj = Integer::Handle(isolate);
|
|
|
|
indexobj = Integer::New(index);
|
|
|
|
args.Add(&indexobj);
|
|
|
|
const Array& kNoArgumentNames = Array::Handle(isolate);
|
|
|
|
return Api::NewHandle(isolate, DartEntry::InvokeDynamic(
|
|
|
|
instance, function, args, kNoArgumentNames));
|
|
|
|
}
|
2011-10-31 21:08:39 +00:00
|
|
|
}
|
2012-08-22 13:42:06 +00:00
|
|
|
return Api::NewError("Object does not implement the 'List' interface");
|
2011-10-31 21:08:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-04-09 21:50:53 +00:00
|
|
|
#define SET_LIST_ELEMENT(isolate, type, obj, index, value) \
|
2012-07-02 21:42:53 +00:00
|
|
|
const type& array = type::Cast(obj); \
|
2012-04-09 21:50:53 +00:00
|
|
|
const Object& value_obj = Object::Handle(isolate, Api::UnwrapHandle(value)); \
|
2012-08-22 13:42:06 +00:00
|
|
|
if (!value_obj.IsNull() && !value_obj.IsInstance()) { \
|
|
|
|
RETURN_TYPE_ERROR(isolate, value, Instance); \
|
|
|
|
} \
|
2012-04-09 21:50:53 +00:00
|
|
|
if ((index >= 0) && (index < array.Length())) { \
|
|
|
|
array.SetAt(index, value_obj); \
|
|
|
|
return Api::Success(isolate); \
|
|
|
|
} \
|
|
|
|
return Api::NewError("Invalid index passed in to set list element"); \
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_ListSetAt(Dart_Handle list,
|
|
|
|
intptr_t index,
|
|
|
|
Dart_Handle value) {
|
2011-11-12 05:55:22 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
2012-04-04 20:31:49 +00:00
|
|
|
const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(list));
|
2011-10-05 05:20:07 +00:00
|
|
|
if (obj.IsArray()) {
|
2011-11-17 06:57:39 +00:00
|
|
|
if (obj.IsImmutableArray()) {
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("Cannot modify immutable array");
|
2011-11-17 06:57:39 +00:00
|
|
|
}
|
2012-04-09 21:50:53 +00:00
|
|
|
SET_LIST_ELEMENT(isolate, Array, obj, index, value);
|
2012-08-22 13:42:06 +00:00
|
|
|
} else if (obj.IsGrowableObjectArray()) {
|
2012-04-09 21:50:53 +00:00
|
|
|
SET_LIST_ELEMENT(isolate, GrowableObjectArray, obj, index, value);
|
2012-08-22 13:42:06 +00:00
|
|
|
} else if (obj.IsError()) {
|
|
|
|
return list;
|
|
|
|
} else {
|
|
|
|
// Check and handle a dart object that implements the List interface.
|
|
|
|
const Instance& instance =
|
|
|
|
Instance::Handle(isolate, GetListInstance(isolate, obj));
|
|
|
|
if (!instance.IsNull()) {
|
2012-12-01 00:34:19 +00:00
|
|
|
String& name = String::Handle(isolate, Symbols::AssignIndexToken());
|
2012-08-22 13:42:06 +00:00
|
|
|
const Function& function =
|
|
|
|
Function::Handle(isolate,
|
|
|
|
Resolver::ResolveDynamic(instance, name, 3, 0));
|
|
|
|
if (!function.IsNull()) {
|
|
|
|
const Integer& index_obj =
|
|
|
|
Integer::Handle(isolate, Integer::New(index));
|
|
|
|
const Object& value_obj =
|
|
|
|
Object::Handle(isolate, Api::UnwrapHandle(value));
|
|
|
|
if (!value_obj.IsNull() && !value_obj.IsInstance()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, value, Instance);
|
|
|
|
}
|
|
|
|
GrowableArray<const Object*> args(2);
|
|
|
|
args.Add(&index_obj);
|
|
|
|
args.Add(&value_obj);
|
|
|
|
const Array& kNoArgumentNames = Array::Handle(isolate);
|
|
|
|
return Api::NewHandle(isolate, DartEntry::InvokeDynamic(
|
|
|
|
instance, function, args, kNoArgumentNames));
|
|
|
|
}
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
2012-08-22 13:42:06 +00:00
|
|
|
return Api::NewError("Object does not implement the 'List' interface");
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-04-09 21:50:53 +00:00
|
|
|
// TODO(hpayer): value should always be smaller then 0xff. Add error handling.
|
|
|
|
#define GET_LIST_ELEMENT_AS_BYTES(isolate, type, obj, native_array, offset, \
|
2012-09-28 11:08:38 +00:00
|
|
|
length) \
|
2012-07-02 21:42:53 +00:00
|
|
|
const type& array = type::Cast(obj); \
|
2012-04-09 21:50:53 +00:00
|
|
|
if (Utils::RangeCheck(offset, length, array.Length())) { \
|
|
|
|
Object& element = Object::Handle(isolate); \
|
|
|
|
for (int i = 0; i < length; i++) { \
|
|
|
|
element = array.At(offset + i); \
|
|
|
|
if (!element.IsInteger()) { \
|
|
|
|
return Api::NewError("%s expects the argument 'list' to be " \
|
|
|
|
"a List of int", CURRENT_FUNC); \
|
|
|
|
} \
|
2012-07-02 21:42:53 +00:00
|
|
|
const Integer& integer = Integer::Cast(element); \
|
2012-04-09 21:50:53 +00:00
|
|
|
native_array[i] = static_cast<uint8_t>(integer.AsInt64Value() & 0xff); \
|
|
|
|
ASSERT(integer.AsInt64Value() <= 0xff); \
|
|
|
|
} \
|
|
|
|
return Api::Success(isolate); \
|
|
|
|
} \
|
|
|
|
return Api::NewError("Invalid length passed in to access array elements"); \
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_ListGetAsBytes(Dart_Handle list,
|
|
|
|
intptr_t offset,
|
|
|
|
uint8_t* native_array,
|
|
|
|
intptr_t length) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
2012-04-04 20:31:49 +00:00
|
|
|
const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(list));
|
2012-11-15 11:03:02 +00:00
|
|
|
if (obj.IsUint8Array() || obj.IsExternalUint8Array() ||
|
2012-12-06 21:53:51 +00:00
|
|
|
obj.IsUint8ClampedArray() || obj.IsExternalUint8ClampedArray() ||
|
2012-11-15 11:03:02 +00:00
|
|
|
obj.IsInt8Array() || obj.IsExternalInt8Array()) {
|
2012-07-02 21:42:53 +00:00
|
|
|
const ByteArray& byte_array = ByteArray::Cast(obj);
|
2012-02-01 21:48:27 +00:00
|
|
|
if (Utils::RangeCheck(offset, length, byte_array.Length())) {
|
|
|
|
ByteArray::Copy(native_array, byte_array, offset, length);
|
2012-04-04 20:31:49 +00:00
|
|
|
return Api::Success(isolate);
|
2012-02-01 21:48:27 +00:00
|
|
|
}
|
|
|
|
return Api::NewError("Invalid length passed in to access list elements");
|
2012-08-22 13:42:06 +00:00
|
|
|
} else if (obj.IsArray()) {
|
2012-04-09 21:50:53 +00:00
|
|
|
GET_LIST_ELEMENT_AS_BYTES(isolate,
|
|
|
|
Array,
|
|
|
|
obj,
|
|
|
|
native_array,
|
|
|
|
offset,
|
2012-08-22 13:42:06 +00:00
|
|
|
length);
|
|
|
|
} else if (obj.IsGrowableObjectArray()) {
|
2012-04-09 21:50:53 +00:00
|
|
|
GET_LIST_ELEMENT_AS_BYTES(isolate,
|
|
|
|
GrowableObjectArray,
|
|
|
|
obj,
|
|
|
|
native_array,
|
|
|
|
offset,
|
|
|
|
length);
|
2012-08-22 13:42:06 +00:00
|
|
|
} else if (obj.IsError()) {
|
|
|
|
return list;
|
|
|
|
} else {
|
|
|
|
// Check and handle a dart object that implements the List interface.
|
|
|
|
const Instance& instance =
|
|
|
|
Instance::Handle(isolate, GetListInstance(isolate, obj));
|
|
|
|
if (!instance.IsNull()) {
|
2012-12-01 00:34:19 +00:00
|
|
|
String& name = String::Handle(isolate, Symbols::IndexToken());
|
2012-08-22 13:42:06 +00:00
|
|
|
const Function& function =
|
|
|
|
Function::Handle(isolate,
|
|
|
|
Resolver::ResolveDynamic(instance, name, 2, 0));
|
|
|
|
if (!function.IsNull()) {
|
|
|
|
Object& result = Object::Handle(isolate);
|
|
|
|
Integer& intobj = Integer::Handle(isolate);
|
|
|
|
for (int i = 0; i < length; i++) {
|
|
|
|
intobj = Integer::New(offset + i);
|
|
|
|
GrowableArray<const Object*> args(1);
|
|
|
|
args.Add(&intobj);
|
|
|
|
const Array& kNoArgumentNames = Array::Handle(isolate);
|
|
|
|
result = DartEntry::InvokeDynamic(
|
|
|
|
instance, function, args, kNoArgumentNames);
|
|
|
|
if (result.IsError()) {
|
|
|
|
return Api::NewHandle(isolate, result.raw());
|
|
|
|
}
|
|
|
|
if (!result.IsInteger()) {
|
|
|
|
return Api::NewError("%s expects the argument 'list' to be "
|
|
|
|
"a List of int", CURRENT_FUNC);
|
|
|
|
}
|
|
|
|
const Integer& integer_result = Integer::Cast(result);
|
|
|
|
ASSERT(integer_result.AsInt64Value() <= 0xff);
|
|
|
|
// TODO(hpayer): value should always be smaller then 0xff. Add error
|
|
|
|
// handling.
|
|
|
|
native_array[i] =
|
|
|
|
static_cast<uint8_t>(integer_result.AsInt64Value() & 0xff);
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
2012-08-22 13:42:06 +00:00
|
|
|
return Api::Success(isolate);
|
2011-10-31 21:08:39 +00:00
|
|
|
}
|
|
|
|
}
|
2012-08-22 13:42:06 +00:00
|
|
|
return Api::NewError("Object does not implement the 'List' interface");
|
2011-10-31 21:08:39 +00:00
|
|
|
}
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
2011-10-31 21:08:39 +00:00
|
|
|
|
2012-04-09 21:50:53 +00:00
|
|
|
#define SET_LIST_ELEMENT_AS_BYTES(isolate, type, obj, native_array, offset, \
|
|
|
|
length) \
|
2012-07-02 21:42:53 +00:00
|
|
|
const type& array = type::Cast(obj); \
|
2012-04-09 21:50:53 +00:00
|
|
|
Integer& integer = Integer::Handle(isolate); \
|
|
|
|
if (Utils::RangeCheck(offset, length, array.Length())) { \
|
|
|
|
for (int i = 0; i < length; i++) { \
|
|
|
|
integer = Integer::New(native_array[i]); \
|
|
|
|
array.SetAt(offset + i, integer); \
|
|
|
|
} \
|
|
|
|
return Api::Success(isolate); \
|
|
|
|
} \
|
|
|
|
return Api::NewError("Invalid length passed in to set array elements"); \
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_ListSetAsBytes(Dart_Handle list,
|
|
|
|
intptr_t offset,
|
|
|
|
uint8_t* native_array,
|
|
|
|
intptr_t length) {
|
2011-11-12 05:55:22 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
2012-04-04 20:31:49 +00:00
|
|
|
const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(list));
|
2012-12-06 21:53:51 +00:00
|
|
|
if (obj.IsUint8Array() || obj.IsExternalUint8Array() ||
|
|
|
|
obj.IsUint8ClampedArray() || obj.IsExternalUint8ClampedArray()) {
|
2012-07-02 21:42:53 +00:00
|
|
|
const ByteArray& byte_array = ByteArray::Cast(obj);
|
2012-02-01 21:48:27 +00:00
|
|
|
if (Utils::RangeCheck(offset, length, byte_array.Length())) {
|
|
|
|
ByteArray::Copy(byte_array, offset, native_array, length);
|
2012-04-04 20:31:49 +00:00
|
|
|
return Api::Success(isolate);
|
2012-02-01 21:48:27 +00:00
|
|
|
}
|
|
|
|
return Api::NewError("Invalid length passed in to set list elements");
|
2012-08-22 13:42:06 +00:00
|
|
|
} else if (obj.IsArray()) {
|
2011-11-17 06:57:39 +00:00
|
|
|
if (obj.IsImmutableArray()) {
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("Cannot modify immutable array");
|
2011-11-17 06:57:39 +00:00
|
|
|
}
|
2012-04-09 21:50:53 +00:00
|
|
|
SET_LIST_ELEMENT_AS_BYTES(isolate,
|
|
|
|
Array,
|
|
|
|
obj,
|
|
|
|
native_array,
|
|
|
|
offset,
|
|
|
|
length);
|
2012-08-22 13:42:06 +00:00
|
|
|
} else if (obj.IsGrowableObjectArray()) {
|
2012-04-09 21:50:53 +00:00
|
|
|
SET_LIST_ELEMENT_AS_BYTES(isolate,
|
|
|
|
GrowableObjectArray,
|
|
|
|
obj,
|
|
|
|
native_array,
|
|
|
|
offset,
|
|
|
|
length);
|
2012-08-22 13:42:06 +00:00
|
|
|
} else if (obj.IsError()) {
|
|
|
|
return list;
|
|
|
|
} else {
|
|
|
|
// Check and handle a dart object that implements the List interface.
|
|
|
|
const Instance& instance =
|
|
|
|
Instance::Handle(isolate, GetListInstance(isolate, obj));
|
|
|
|
if (!instance.IsNull()) {
|
2012-12-01 00:34:19 +00:00
|
|
|
String& name = String::Handle(isolate, Symbols::AssignIndexToken());
|
2012-08-22 13:42:06 +00:00
|
|
|
const Function& function =
|
|
|
|
Function::Handle(isolate,
|
|
|
|
Resolver::ResolveDynamic(instance, name, 3, 0));
|
|
|
|
if (!function.IsNull()) {
|
|
|
|
Integer& indexobj = Integer::Handle(isolate);
|
|
|
|
Integer& valueobj = Integer::Handle(isolate);
|
|
|
|
for (int i = 0; i < length; i++) {
|
|
|
|
indexobj = Integer::New(offset + i);
|
|
|
|
valueobj = Integer::New(native_array[i]);
|
|
|
|
GrowableArray<const Object*> args(2);
|
|
|
|
args.Add(&indexobj);
|
|
|
|
args.Add(&valueobj);
|
|
|
|
const Array& kNoArgumentNames = Array::Handle(isolate);
|
|
|
|
const Object& result = Object::Handle(
|
|
|
|
isolate,
|
|
|
|
DartEntry::InvokeDynamic(
|
|
|
|
instance, function, args, kNoArgumentNames));
|
|
|
|
if (result.IsError()) {
|
|
|
|
return Api::NewHandle(isolate, result.raw());
|
|
|
|
}
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
2012-08-22 13:42:06 +00:00
|
|
|
return Api::Success(isolate);
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
2011-10-31 21:08:39 +00:00
|
|
|
}
|
2012-08-22 13:42:06 +00:00
|
|
|
return Api::NewError("Object does not implement the 'List' interface");
|
2011-10-31 21:08:39 +00:00
|
|
|
}
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-01-26 02:42:08 +00:00
|
|
|
// --- Byte Arrays ---
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT bool Dart_IsByteArray(Dart_Handle object) {
|
2012-05-31 12:41:37 +00:00
|
|
|
return RawObject::IsByteArrayClassId(Api::ClassId(object));
|
2012-01-26 02:42:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-11-01 07:53:33 +00:00
|
|
|
DART_EXPORT bool Dart_IsByteArrayExternal(Dart_Handle object) {
|
|
|
|
return RawObject::IsExternalByteArrayClassId(Api::ClassId(object));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-01-26 02:42:08 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_NewByteArray(intptr_t length) {
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
2012-08-01 18:22:30 +00:00
|
|
|
CHECK_LENGTH(length, Uint8Array::kMaxElements);
|
2012-05-04 23:16:09 +00:00
|
|
|
return Api::NewHandle(isolate, Uint8Array::New(length));
|
2012-01-26 02:42:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-02-11 04:34:44 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_NewExternalByteArray(uint8_t* data,
|
|
|
|
intptr_t length,
|
|
|
|
void* peer,
|
|
|
|
Dart_PeerFinalizer callback) {
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
2012-02-11 04:34:44 +00:00
|
|
|
if (data == NULL && length != 0) {
|
2012-07-09 23:57:08 +00:00
|
|
|
RETURN_NULL_ERROR(data);
|
2012-02-11 04:34:44 +00:00
|
|
|
}
|
2012-08-01 18:22:30 +00:00
|
|
|
CHECK_LENGTH(length, ExternalUint8Array::kMaxElements);
|
2012-04-06 17:05:50 +00:00
|
|
|
return Api::NewHandle(
|
2012-05-04 23:16:09 +00:00
|
|
|
isolate, ExternalUint8Array::New(data, length, peer, callback));
|
2012-02-11 04:34:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-11-01 07:53:33 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_ExternalByteArrayGetData(Dart_Handle object,
|
|
|
|
void** data) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
const ExternalUint8Array& array =
|
|
|
|
Api::UnwrapExternalUint8ArrayHandle(isolate, object);
|
|
|
|
if (array.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, object, ExternalUint8Array);
|
|
|
|
}
|
|
|
|
if (data == NULL) {
|
|
|
|
RETURN_NULL_ERROR(data);
|
|
|
|
}
|
|
|
|
*data = array.GetData();
|
|
|
|
return Api::Success(isolate);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-02-11 04:34:44 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_ExternalByteArrayGetPeer(Dart_Handle object,
|
|
|
|
void** peer) {
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
2012-05-04 23:16:09 +00:00
|
|
|
const ExternalUint8Array& array =
|
|
|
|
Api::UnwrapExternalUint8ArrayHandle(isolate, object);
|
2012-02-11 04:34:44 +00:00
|
|
|
if (array.IsNull()) {
|
2012-05-04 23:16:09 +00:00
|
|
|
RETURN_TYPE_ERROR(isolate, object, ExternalUint8Array);
|
2012-02-11 04:34:44 +00:00
|
|
|
}
|
|
|
|
if (peer == NULL) {
|
2012-07-09 23:57:08 +00:00
|
|
|
RETURN_NULL_ERROR(peer);
|
2012-02-11 04:34:44 +00:00
|
|
|
}
|
|
|
|
*peer = array.GetPeer();
|
2012-04-04 20:31:49 +00:00
|
|
|
return Api::Success(isolate);
|
2012-02-11 04:34:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-02-15 02:51:11 +00:00
|
|
|
template<typename T>
|
|
|
|
Dart_Handle ByteArrayGetAt(T* value, Dart_Handle array, intptr_t offset) {
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
CHECK_ISOLATE(isolate);
|
|
|
|
const ByteArray& array_obj = Api::UnwrapByteArrayHandle(isolate, array);
|
2012-02-15 02:51:11 +00:00
|
|
|
if (array_obj.IsNull()) {
|
2012-04-04 20:31:49 +00:00
|
|
|
RETURN_TYPE_ERROR(isolate, array, ByteArray);
|
2012-02-15 02:51:11 +00:00
|
|
|
}
|
|
|
|
intptr_t length = sizeof(T);
|
2012-05-04 23:16:09 +00:00
|
|
|
if (!Utils::RangeCheck(offset, length, array_obj.ByteLength())) {
|
2012-02-15 02:51:11 +00:00
|
|
|
return Api::NewError("Invalid index passed in to get byte array element");
|
|
|
|
}
|
|
|
|
uint8_t* dst = reinterpret_cast<uint8_t*>(value);
|
|
|
|
ByteArray::Copy(dst, array_obj, offset, length);
|
2012-04-04 20:31:49 +00:00
|
|
|
return Api::Success(isolate);
|
2012-02-15 02:51:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
Dart_Handle ByteArraySetAt(Dart_Handle array, intptr_t offset, T value) {
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
CHECK_ISOLATE(isolate);
|
|
|
|
const ByteArray& array_obj = Api::UnwrapByteArrayHandle(isolate, array);
|
2012-02-15 02:51:11 +00:00
|
|
|
if (array_obj.IsNull()) {
|
2012-04-04 20:31:49 +00:00
|
|
|
RETURN_TYPE_ERROR(isolate, array, ByteArray);
|
2012-02-15 02:51:11 +00:00
|
|
|
}
|
|
|
|
intptr_t length = sizeof(T);
|
2012-05-04 23:16:09 +00:00
|
|
|
if (!Utils::RangeCheck(offset, length, array_obj.ByteLength())) {
|
2012-02-15 02:51:11 +00:00
|
|
|
return Api::NewError("Invalid index passed in to get byte array element");
|
|
|
|
}
|
|
|
|
const uint8_t* src = reinterpret_cast<uint8_t*>(&value);
|
|
|
|
ByteArray::Copy(array_obj, offset, src, length);
|
2012-04-04 20:31:49 +00:00
|
|
|
return Api::Success(isolate);
|
2012-02-15 02:51:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_ByteArrayGetInt8At(Dart_Handle array,
|
2012-05-04 23:16:09 +00:00
|
|
|
intptr_t byte_offset,
|
2012-02-15 02:51:11 +00:00
|
|
|
int8_t* value) {
|
2012-05-04 23:16:09 +00:00
|
|
|
return ByteArrayGetAt(value, array, byte_offset);
|
2012-02-15 02:51:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_ByteArraySetInt8At(Dart_Handle array,
|
2012-05-04 23:16:09 +00:00
|
|
|
intptr_t byte_offset,
|
2012-02-15 02:51:11 +00:00
|
|
|
int8_t value) {
|
2012-05-04 23:16:09 +00:00
|
|
|
return ByteArraySetAt(array, byte_offset, value);
|
2012-02-15 02:51:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_ByteArrayGetUint8At(Dart_Handle array,
|
2012-05-04 23:16:09 +00:00
|
|
|
intptr_t byte_offset,
|
2012-02-15 02:51:11 +00:00
|
|
|
uint8_t* value) {
|
2012-05-04 23:16:09 +00:00
|
|
|
return ByteArrayGetAt(value, array, byte_offset);
|
2012-02-15 02:51:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_ByteArraySetUint8At(Dart_Handle array,
|
2012-05-04 23:16:09 +00:00
|
|
|
intptr_t byte_offset,
|
2012-02-15 02:51:11 +00:00
|
|
|
uint8_t value) {
|
2012-05-04 23:16:09 +00:00
|
|
|
return ByteArraySetAt(array, byte_offset, value);
|
2012-02-15 02:51:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_ByteArrayGetInt16At(Dart_Handle array,
|
2012-05-04 23:16:09 +00:00
|
|
|
intptr_t byte_offset,
|
2012-02-15 02:51:11 +00:00
|
|
|
int16_t* value) {
|
2012-05-04 23:16:09 +00:00
|
|
|
return ByteArrayGetAt(value, array, byte_offset);
|
2012-02-15 02:51:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_ByteArraySetInt16At(Dart_Handle array,
|
2012-05-04 23:16:09 +00:00
|
|
|
intptr_t byte_offset,
|
2012-02-15 02:51:11 +00:00
|
|
|
int16_t value) {
|
2012-05-04 23:16:09 +00:00
|
|
|
return ByteArraySetAt(array, byte_offset, value);
|
2012-02-15 02:51:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_ByteArrayGetUint16At(Dart_Handle array,
|
2012-05-04 23:16:09 +00:00
|
|
|
intptr_t byte_offset,
|
2012-02-15 02:51:11 +00:00
|
|
|
uint16_t* value) {
|
2012-05-04 23:16:09 +00:00
|
|
|
return ByteArrayGetAt(value, array, byte_offset);
|
2012-02-15 02:51:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_ByteArraySetUint16At(Dart_Handle array,
|
2012-05-04 23:16:09 +00:00
|
|
|
intptr_t byte_offset,
|
2012-02-15 02:51:11 +00:00
|
|
|
uint16_t value) {
|
2012-05-04 23:16:09 +00:00
|
|
|
return ByteArraySetAt(array, byte_offset, value);
|
2012-02-15 02:51:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_ByteArrayGetInt32At(Dart_Handle array,
|
2012-05-04 23:16:09 +00:00
|
|
|
intptr_t byte_offset,
|
2012-02-15 02:51:11 +00:00
|
|
|
int32_t* value) {
|
2012-05-04 23:16:09 +00:00
|
|
|
return ByteArrayGetAt(value, array, byte_offset);
|
2012-02-15 02:51:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_ByteArraySetInt32At(Dart_Handle array,
|
2012-05-04 23:16:09 +00:00
|
|
|
intptr_t byte_offset,
|
2012-02-15 02:51:11 +00:00
|
|
|
int32_t value) {
|
2012-05-04 23:16:09 +00:00
|
|
|
return ByteArraySetAt(array, byte_offset, value);
|
2012-02-15 02:51:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_ByteArrayGetUint32At(Dart_Handle array,
|
2012-05-04 23:16:09 +00:00
|
|
|
intptr_t byte_offset,
|
2012-02-15 02:51:11 +00:00
|
|
|
uint32_t* value) {
|
2012-05-04 23:16:09 +00:00
|
|
|
return ByteArrayGetAt(value, array, byte_offset);
|
2012-02-15 02:51:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_ByteArraySetUint32At(Dart_Handle array,
|
2012-05-04 23:16:09 +00:00
|
|
|
intptr_t byte_offset,
|
2012-02-15 02:51:11 +00:00
|
|
|
uint32_t value) {
|
2012-05-04 23:16:09 +00:00
|
|
|
return ByteArraySetAt(array, byte_offset, value);
|
2012-02-15 02:51:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_ByteArrayGetInt64At(Dart_Handle array,
|
2012-05-04 23:16:09 +00:00
|
|
|
intptr_t byte_offset,
|
2012-02-15 02:51:11 +00:00
|
|
|
int64_t* value) {
|
2012-05-04 23:16:09 +00:00
|
|
|
return ByteArrayGetAt(value, array, byte_offset);
|
2012-02-15 02:51:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_ByteArraySetInt64At(Dart_Handle array,
|
2012-05-04 23:16:09 +00:00
|
|
|
intptr_t byte_offset,
|
2012-02-15 02:51:11 +00:00
|
|
|
int64_t value) {
|
2012-05-04 23:16:09 +00:00
|
|
|
return ByteArraySetAt(array, byte_offset, value);
|
2012-02-15 02:51:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_ByteArrayGetUint64At(Dart_Handle array,
|
2012-05-04 23:16:09 +00:00
|
|
|
intptr_t byte_offset,
|
2012-02-15 02:51:11 +00:00
|
|
|
uint64_t* value) {
|
2012-05-04 23:16:09 +00:00
|
|
|
return ByteArrayGetAt(value, array, byte_offset);
|
2012-02-15 02:51:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_ByteArraySetUint64At(Dart_Handle array,
|
2012-05-04 23:16:09 +00:00
|
|
|
intptr_t byte_offset,
|
2012-02-15 02:51:11 +00:00
|
|
|
uint64_t value) {
|
2012-05-04 23:16:09 +00:00
|
|
|
return ByteArraySetAt(array, byte_offset, value);
|
2012-02-15 02:51:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_ByteArrayGetFloat32At(Dart_Handle array,
|
2012-05-04 23:16:09 +00:00
|
|
|
intptr_t byte_offset,
|
2012-02-15 02:51:11 +00:00
|
|
|
float* value) {
|
2012-05-04 23:16:09 +00:00
|
|
|
return ByteArrayGetAt(value, array, byte_offset);
|
2012-02-15 02:51:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_ByteArraySetFloat32At(Dart_Handle array,
|
2012-05-04 23:16:09 +00:00
|
|
|
intptr_t byte_offset,
|
2012-02-15 02:51:11 +00:00
|
|
|
float value) {
|
2012-05-04 23:16:09 +00:00
|
|
|
return ByteArraySetAt(array, byte_offset, value);
|
2012-02-15 02:51:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_ByteArrayGetFloat64At(Dart_Handle array,
|
2012-05-04 23:16:09 +00:00
|
|
|
intptr_t byte_offset,
|
2012-02-15 02:51:11 +00:00
|
|
|
double* value) {
|
2012-05-04 23:16:09 +00:00
|
|
|
return ByteArrayGetAt(value, array, byte_offset);
|
2012-02-15 02:51:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_ByteArraySetFloat64At(Dart_Handle array,
|
2012-05-04 23:16:09 +00:00
|
|
|
intptr_t byte_offset,
|
2012-02-15 02:51:11 +00:00
|
|
|
double value) {
|
2012-05-04 23:16:09 +00:00
|
|
|
return ByteArraySetAt(array, byte_offset, value);
|
2012-02-15 02:51:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
// --- Closures ---
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT bool Dart_IsClosure(Dart_Handle object) {
|
2012-05-14 17:58:59 +00:00
|
|
|
// We can't use a fast class index check here because there are many
|
|
|
|
// different signature classes for closures.
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
2012-10-11 20:34:08 +00:00
|
|
|
const Instance& closure_obj = Api::UnwrapInstanceHandle(isolate, object);
|
|
|
|
return (!closure_obj.IsNull() && closure_obj.IsClosure());
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-07-24 17:59:12 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_ClosureFunction(Dart_Handle closure) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
2012-10-11 20:34:08 +00:00
|
|
|
const Instance& closure_obj = Api::UnwrapInstanceHandle(isolate, closure);
|
|
|
|
if (closure_obj.IsNull() || !closure_obj.IsClosure()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, closure, Instance);
|
2012-07-24 17:59:12 +00:00
|
|
|
}
|
2012-10-11 20:34:08 +00:00
|
|
|
|
2012-07-24 17:59:12 +00:00
|
|
|
ASSERT(ClassFinalizer::AllClassesFinalized());
|
|
|
|
|
2012-10-11 20:34:08 +00:00
|
|
|
RawFunction* rf = Closure::function(closure_obj);
|
2012-07-24 17:59:12 +00:00
|
|
|
return Api::NewHandle(isolate, rf);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_InvokeClosure(Dart_Handle closure,
|
|
|
|
int number_of_arguments,
|
|
|
|
Dart_Handle* arguments) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
2012-10-11 20:34:08 +00:00
|
|
|
const Instance& closure_obj = Api::UnwrapInstanceHandle(isolate, closure);
|
|
|
|
if (closure_obj.IsNull() || !closure_obj.IsClosure()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, closure, Instance);
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
2012-08-22 13:42:06 +00:00
|
|
|
if (number_of_arguments < 0) {
|
|
|
|
return Api::NewError(
|
|
|
|
"%s expects argument 'number_of_arguments' to be non-negative.",
|
|
|
|
CURRENT_FUNC);
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
|
|
|
ASSERT(ClassFinalizer::AllClassesFinalized());
|
|
|
|
|
|
|
|
// Now try to invoke the closure.
|
|
|
|
GrowableArray<const Object*> dart_arguments(number_of_arguments);
|
|
|
|
for (int i = 0; i < number_of_arguments; i++) {
|
2012-04-04 20:31:49 +00:00
|
|
|
const Object& arg =
|
|
|
|
Object::Handle(isolate, Api::UnwrapHandle(arguments[i]));
|
2012-08-22 13:42:06 +00:00
|
|
|
if (!arg.IsNull() && !arg.IsInstance()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, arguments[i], Instance);
|
|
|
|
}
|
2011-11-22 19:42:38 +00:00
|
|
|
dart_arguments.Add(&arg);
|
|
|
|
}
|
2012-04-04 20:31:49 +00:00
|
|
|
const Array& kNoArgumentNames = Array::Handle(isolate);
|
2012-04-06 17:05:50 +00:00
|
|
|
return Api::NewHandle(
|
2012-04-04 20:31:49 +00:00
|
|
|
isolate,
|
2012-02-02 19:05:06 +00:00
|
|
|
DartEntry::InvokeClosure(closure_obj, dart_arguments, kNoArgumentNames));
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-11-30 01:26:31 +00:00
|
|
|
// --- Classes ---
|
2012-06-12 21:07:49 +00:00
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT bool Dart_IsClass(Dart_Handle handle) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(handle));
|
2012-11-30 01:26:31 +00:00
|
|
|
return obj.IsClass();
|
2012-06-12 21:07:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-11-30 01:26:31 +00:00
|
|
|
DART_EXPORT bool Dart_IsAbstractClass(Dart_Handle handle) {
|
2012-06-12 21:07:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(handle));
|
|
|
|
if (obj.IsClass()) {
|
2012-11-30 01:26:31 +00:00
|
|
|
return Class::Cast(obj).is_abstract();
|
2012-06-12 21:07:49 +00:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_ClassName(Dart_Handle clazz) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
2012-08-22 13:42:06 +00:00
|
|
|
const Class& cls = Api::UnwrapClassHandle(isolate, clazz);
|
2012-06-12 21:07:49 +00:00
|
|
|
if (cls.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, clazz, Class);
|
|
|
|
}
|
2012-08-08 17:22:26 +00:00
|
|
|
return Api::NewHandle(isolate, cls.UserVisibleName());
|
2012-06-12 21:07:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_ClassGetLibrary(Dart_Handle clazz) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
2012-08-22 13:42:06 +00:00
|
|
|
const Class& cls = Api::UnwrapClassHandle(isolate, clazz);
|
2012-06-12 21:07:49 +00:00
|
|
|
if (cls.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, clazz, Class);
|
|
|
|
}
|
2012-07-09 23:57:08 +00:00
|
|
|
|
|
|
|
#if defined(DEBUG)
|
|
|
|
const Library& lib = Library::Handle(cls.library());
|
|
|
|
if (lib.IsNull()) {
|
2012-09-13 17:47:25 +00:00
|
|
|
// ASSERT(cls.IsDynamicClass() || cls.IsVoidClass());
|
|
|
|
if (!cls.IsDynamicClass() && !cls.IsVoidClass()) {
|
|
|
|
fprintf(stderr, "NO LIBRARY: %s\n", cls.ToCString());
|
|
|
|
}
|
2012-07-09 23:57:08 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2012-06-12 21:07:49 +00:00
|
|
|
return Api::NewHandle(isolate, cls.library());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_ClassGetInterfaceCount(Dart_Handle clazz,
|
|
|
|
intptr_t* count) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
2012-08-22 13:42:06 +00:00
|
|
|
const Class& cls = Api::UnwrapClassHandle(isolate, clazz);
|
2012-06-12 21:07:49 +00:00
|
|
|
if (cls.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, clazz, Class);
|
|
|
|
}
|
|
|
|
|
|
|
|
const Array& interface_types = Array::Handle(isolate, cls.interfaces());
|
|
|
|
if (interface_types.IsNull()) {
|
|
|
|
*count = 0;
|
|
|
|
} else {
|
|
|
|
*count = interface_types.Length();
|
|
|
|
}
|
|
|
|
return Api::Success(isolate);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_ClassGetInterfaceAt(Dart_Handle clazz,
|
|
|
|
intptr_t index) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
2012-08-22 13:42:06 +00:00
|
|
|
const Class& cls = Api::UnwrapClassHandle(isolate, clazz);
|
2012-06-12 21:07:49 +00:00
|
|
|
if (cls.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, clazz, Class);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Finalize all classes.
|
|
|
|
const char* msg = CheckIsolateState(isolate);
|
|
|
|
if (msg != NULL) {
|
2012-09-06 00:58:25 +00:00
|
|
|
return Api::NewError("%s", msg);
|
2012-06-12 21:07:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const Array& interface_types = Array::Handle(isolate, cls.interfaces());
|
|
|
|
if (index < 0 || index >= interface_types.Length()) {
|
|
|
|
return Api::NewError("%s: argument 'index' out of bounds.", CURRENT_FUNC);
|
|
|
|
}
|
|
|
|
Type& interface_type = Type::Handle(isolate);
|
|
|
|
interface_type ^= interface_types.At(index);
|
|
|
|
if (interface_type.HasResolvedTypeClass()) {
|
|
|
|
return Api::NewHandle(isolate, interface_type.type_class());
|
|
|
|
}
|
|
|
|
const String& type_name =
|
|
|
|
String::Handle(isolate, interface_type.TypeClassName());
|
|
|
|
return Api::NewError("%s: internal error: found unresolved type class '%s'.",
|
|
|
|
CURRENT_FUNC, type_name.ToCString());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-13 17:47:25 +00:00
|
|
|
DART_EXPORT bool Dart_ClassIsTypedef(Dart_Handle clazz) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
const Class& cls = Api::UnwrapClassHandle(isolate, clazz);
|
|
|
|
if (cls.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, clazz, Class);
|
|
|
|
}
|
|
|
|
// For now we represent typedefs as non-canonical signature classes.
|
|
|
|
// I anticipate this may change if we make typedefs more general.
|
|
|
|
return cls.IsSignatureClass() && !cls.IsCanonicalSignatureClass();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_ClassGetTypedefReferent(Dart_Handle clazz) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
const Class& cls = Api::UnwrapClassHandle(isolate, clazz);
|
|
|
|
if (cls.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, clazz, Class);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!cls.IsSignatureClass() && !cls.IsCanonicalSignatureClass()) {
|
|
|
|
const String& cls_name = String::Handle(cls.UserVisibleName());
|
|
|
|
return Api::NewError("%s: class '%s' is not a typedef class. "
|
|
|
|
"See Dart_ClassIsTypedef.",
|
|
|
|
CURRENT_FUNC, cls_name.ToCString());
|
|
|
|
}
|
|
|
|
|
|
|
|
const Function& func = Function::Handle(isolate, cls.signature_function());
|
|
|
|
return Api::NewHandle(isolate, func.signature_class());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT bool Dart_ClassIsFunctionType(Dart_Handle clazz) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
const Class& cls = Api::UnwrapClassHandle(isolate, clazz);
|
|
|
|
if (cls.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, clazz, Class);
|
|
|
|
}
|
|
|
|
// A class represents a function type when it is a canonical
|
|
|
|
// signature class.
|
|
|
|
return cls.IsCanonicalSignatureClass();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_ClassGetFunctionTypeSignature(Dart_Handle clazz) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
const Class& cls = Api::UnwrapClassHandle(isolate, clazz);
|
|
|
|
if (cls.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, clazz, Class);
|
|
|
|
}
|
|
|
|
if (!cls.IsCanonicalSignatureClass()) {
|
|
|
|
const String& cls_name = String::Handle(cls.UserVisibleName());
|
|
|
|
return Api::NewError("%s: class '%s' is not a function-type class. "
|
|
|
|
"See Dart_ClassIsFunctionType.",
|
|
|
|
CURRENT_FUNC, cls_name.ToCString());
|
|
|
|
}
|
|
|
|
return Api::NewHandle(isolate, cls.signature_function());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-07-09 23:57:08 +00:00
|
|
|
// --- Function and Variable Reflection ---
|
|
|
|
|
|
|
|
|
|
|
|
// Outside of the vm, we expose setter names with a trailing '='.
|
|
|
|
static bool HasExternalSetterSuffix(const String& name) {
|
|
|
|
return name.CharAt(name.Length() - 1) == '=';
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static RawString* RemoveExternalSetterSuffix(const String& name) {
|
|
|
|
ASSERT(HasExternalSetterSuffix(name));
|
|
|
|
return String::SubString(name, 0, name.Length() - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_GetFunctionNames(Dart_Handle target) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(target));
|
|
|
|
if (obj.IsError()) {
|
|
|
|
return target;
|
|
|
|
}
|
|
|
|
|
|
|
|
const GrowableObjectArray& names =
|
|
|
|
GrowableObjectArray::Handle(isolate, GrowableObjectArray::New());
|
|
|
|
Function& func = Function::Handle();
|
|
|
|
String& name = String::Handle();
|
|
|
|
|
|
|
|
if (obj.IsClass()) {
|
|
|
|
const Class& cls = Class::Cast(obj);
|
|
|
|
const Array& func_array = Array::Handle(cls.functions());
|
|
|
|
|
2012-10-12 22:40:24 +00:00
|
|
|
// Some special types like 'dynamic' have a null functions list.
|
2012-07-09 23:57:08 +00:00
|
|
|
if (!func_array.IsNull()) {
|
|
|
|
for (intptr_t i = 0; i < func_array.Length(); ++i) {
|
|
|
|
func ^= func_array.At(i);
|
|
|
|
|
|
|
|
// Skip implicit getters and setters.
|
|
|
|
if (func.kind() == RawFunction::kImplicitGetter ||
|
|
|
|
func.kind() == RawFunction::kImplicitSetter ||
|
|
|
|
func.kind() == RawFunction::kConstImplicitGetter) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2012-08-08 17:22:26 +00:00
|
|
|
name = func.UserVisibleName();
|
2012-07-09 23:57:08 +00:00
|
|
|
names.Add(name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (obj.IsLibrary()) {
|
|
|
|
const Library& lib = Library::Cast(obj);
|
|
|
|
DictionaryIterator it(lib);
|
|
|
|
Object& obj = Object::Handle();
|
|
|
|
while (it.HasNext()) {
|
|
|
|
obj = it.GetNext();
|
|
|
|
if (obj.IsFunction()) {
|
|
|
|
func ^= obj.raw();
|
2012-08-08 17:22:26 +00:00
|
|
|
name = func.UserVisibleName();
|
2012-07-09 23:57:08 +00:00
|
|
|
names.Add(name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return Api::NewError(
|
|
|
|
"%s expects argument 'target' to be a class or library.",
|
|
|
|
CURRENT_FUNC);
|
|
|
|
}
|
|
|
|
return Api::NewHandle(isolate, Array::MakeArray(names));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_LookupFunction(Dart_Handle target,
|
|
|
|
Dart_Handle function_name) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(target));
|
|
|
|
if (obj.IsError()) {
|
|
|
|
return target;
|
|
|
|
}
|
|
|
|
const String& func_name = Api::UnwrapStringHandle(isolate, function_name);
|
|
|
|
if (func_name.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, function_name, String);
|
|
|
|
}
|
|
|
|
|
|
|
|
Function& func = Function::Handle(isolate);
|
|
|
|
String& tmp_name = String::Handle(isolate);
|
|
|
|
if (obj.IsClass()) {
|
|
|
|
const Class& cls = Class::Cast(obj);
|
|
|
|
|
|
|
|
// Case 1. Lookup the unmodified function name.
|
|
|
|
func = cls.LookupFunction(func_name);
|
|
|
|
|
|
|
|
// Case 2. Lookup the function without the external setter suffix
|
|
|
|
// '='. Make sure to do this check after the regular lookup, so
|
|
|
|
// that we don't interfere with operator lookups (like ==).
|
|
|
|
if (func.IsNull() && HasExternalSetterSuffix(func_name)) {
|
|
|
|
tmp_name = RemoveExternalSetterSuffix(func_name);
|
|
|
|
tmp_name = Field::SetterName(tmp_name);
|
|
|
|
func = cls.LookupFunction(tmp_name);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Case 3. Lookup the funciton with the getter prefix prepended.
|
|
|
|
if (func.IsNull()) {
|
|
|
|
tmp_name = Field::GetterName(func_name);
|
|
|
|
func = cls.LookupFunction(tmp_name);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Case 4. Lookup the function with a . appended to find the
|
|
|
|
// unnamed constructor.
|
|
|
|
if (func.IsNull()) {
|
2012-12-10 18:24:34 +00:00
|
|
|
tmp_name = String::Concat(func_name, Symbols::DotHandle());
|
2012-07-09 23:57:08 +00:00
|
|
|
func = cls.LookupFunction(tmp_name);
|
|
|
|
}
|
|
|
|
} else if (obj.IsLibrary()) {
|
|
|
|
const Library& lib = Library::Cast(obj);
|
|
|
|
|
|
|
|
// Case 1. Lookup the unmodified function name.
|
|
|
|
func = lib.LookupFunctionAllowPrivate(func_name);
|
|
|
|
|
|
|
|
// Case 2. Lookup the function without the external setter suffix
|
|
|
|
// '='. Make sure to do this check after the regular lookup, so
|
|
|
|
// that we don't interfere with operator lookups (like ==).
|
|
|
|
if (func.IsNull() && HasExternalSetterSuffix(func_name)) {
|
|
|
|
tmp_name = RemoveExternalSetterSuffix(func_name);
|
|
|
|
tmp_name = Field::SetterName(tmp_name);
|
|
|
|
func = lib.LookupFunctionAllowPrivate(tmp_name);
|
|
|
|
}
|
|
|
|
|
2012-08-29 08:35:43 +00:00
|
|
|
// Case 3. Lookup the function with the getter prefix prepended.
|
2012-07-09 23:57:08 +00:00
|
|
|
if (func.IsNull()) {
|
|
|
|
tmp_name = Field::GetterName(func_name);
|
|
|
|
func = lib.LookupFunctionAllowPrivate(tmp_name);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return Api::NewError(
|
|
|
|
"%s expects argument 'target' to be a class or library.",
|
|
|
|
CURRENT_FUNC);
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(DEBUG)
|
|
|
|
if (!func.IsNull()) {
|
|
|
|
// We only provide access to a subset of function kinds.
|
|
|
|
RawFunction::Kind func_kind = func.kind();
|
2012-07-20 22:24:49 +00:00
|
|
|
ASSERT(func_kind == RawFunction::kRegularFunction ||
|
2012-07-09 23:57:08 +00:00
|
|
|
func_kind == RawFunction::kGetterFunction ||
|
|
|
|
func_kind == RawFunction::kSetterFunction ||
|
2012-07-31 21:26:28 +00:00
|
|
|
func_kind == RawFunction::kConstructor);
|
2012-07-09 23:57:08 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return Api::NewHandle(isolate, func.raw());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT bool Dart_IsFunction(Dart_Handle handle) {
|
2012-08-08 19:46:23 +00:00
|
|
|
return Api::ClassId(handle) == kFunctionCid;
|
2012-07-09 23:57:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_FunctionName(Dart_Handle function) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
const Function& func = Api::UnwrapFunctionHandle(isolate, function);
|
|
|
|
if (func.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, function, Function);
|
|
|
|
}
|
2012-08-08 17:22:26 +00:00
|
|
|
return Api::NewHandle(isolate, func.UserVisibleName());
|
2012-07-09 23:57:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-08-03 22:56:21 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_FunctionOwner(Dart_Handle function) {
|
2012-07-31 22:47:52 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
const Function& func = Api::UnwrapFunctionHandle(isolate, function);
|
|
|
|
if (func.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, function, Function);
|
|
|
|
}
|
2012-08-03 22:56:21 +00:00
|
|
|
if (func.IsNonImplicitClosureFunction()) {
|
|
|
|
RawFunction* parent_function = func.parent_function();
|
|
|
|
return Api::NewHandle(isolate, parent_function);
|
|
|
|
}
|
2012-08-14 00:38:01 +00:00
|
|
|
const Class& owner = Class::Handle(func.Owner());
|
2012-07-31 22:47:52 +00:00
|
|
|
ASSERT(!owner.IsNull());
|
|
|
|
if (owner.IsTopLevel()) {
|
|
|
|
// Top-level functions are implemented as members of a hidden class. We hide
|
|
|
|
// that class here and instead answer the library.
|
|
|
|
#if defined(DEBUG)
|
|
|
|
const Library& lib = Library::Handle(owner.library());
|
|
|
|
if (lib.IsNull()) {
|
|
|
|
ASSERT(owner.IsDynamicClass() || owner.IsVoidClass());
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return Api::NewHandle(isolate, owner.library());
|
|
|
|
} else {
|
|
|
|
return Api::NewHandle(isolate, owner.raw());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-07-09 23:57:08 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_FunctionIsAbstract(Dart_Handle function,
|
|
|
|
bool* is_abstract) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
if (is_abstract == NULL) {
|
|
|
|
RETURN_NULL_ERROR(is_abstract);
|
|
|
|
}
|
|
|
|
const Function& func = Api::UnwrapFunctionHandle(isolate, function);
|
|
|
|
if (func.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, function, Function);
|
|
|
|
}
|
2012-07-31 21:26:28 +00:00
|
|
|
*is_abstract = func.is_abstract();
|
2012-07-09 23:57:08 +00:00
|
|
|
return Api::Success(isolate);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_FunctionIsStatic(Dart_Handle function,
|
|
|
|
bool* is_static) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
if (is_static == NULL) {
|
|
|
|
RETURN_NULL_ERROR(is_static);
|
|
|
|
}
|
|
|
|
const Function& func = Api::UnwrapFunctionHandle(isolate, function);
|
|
|
|
if (func.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, function, Function);
|
|
|
|
}
|
|
|
|
*is_static = func.is_static();
|
|
|
|
return Api::Success(isolate);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_FunctionIsConstructor(Dart_Handle function,
|
|
|
|
bool* is_constructor) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
if (is_constructor == NULL) {
|
|
|
|
RETURN_NULL_ERROR(is_constructor);
|
|
|
|
}
|
|
|
|
const Function& func = Api::UnwrapFunctionHandle(isolate, function);
|
|
|
|
if (func.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, function, Function);
|
|
|
|
}
|
|
|
|
*is_constructor = func.kind() == RawFunction::kConstructor;
|
|
|
|
return Api::Success(isolate);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_FunctionIsGetter(Dart_Handle function,
|
|
|
|
bool* is_getter) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
if (is_getter == NULL) {
|
|
|
|
RETURN_NULL_ERROR(is_getter);
|
|
|
|
}
|
|
|
|
const Function& func = Api::UnwrapFunctionHandle(isolate, function);
|
|
|
|
if (func.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, function, Function);
|
|
|
|
}
|
2012-08-10 22:53:34 +00:00
|
|
|
*is_getter = func.IsGetterFunction();
|
2012-07-09 23:57:08 +00:00
|
|
|
return Api::Success(isolate);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_FunctionIsSetter(Dart_Handle function,
|
|
|
|
bool* is_setter) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
if (is_setter == NULL) {
|
|
|
|
RETURN_NULL_ERROR(is_setter);
|
|
|
|
}
|
|
|
|
const Function& func = Api::UnwrapFunctionHandle(isolate, function);
|
|
|
|
if (func.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, function, Function);
|
|
|
|
}
|
2012-07-31 21:26:28 +00:00
|
|
|
*is_setter = (func.kind() == RawFunction::kSetterFunction);
|
2012-07-09 23:57:08 +00:00
|
|
|
return Api::Success(isolate);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-13 17:47:25 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_FunctionReturnType(Dart_Handle function) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
const Function& func = Api::UnwrapFunctionHandle(isolate, function);
|
|
|
|
if (func.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, function, Function);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (func.kind() == RawFunction::kConstructor) {
|
|
|
|
// Special case the return type for constructors. Inside the vm
|
2012-10-12 22:40:24 +00:00
|
|
|
// we mark them as returning dynamic, but for the purposes of
|
2012-09-13 17:47:25 +00:00
|
|
|
// reflection, they return the type of the class being
|
|
|
|
// constructed.
|
|
|
|
return Api::NewHandle(isolate, func.Owner());
|
|
|
|
} else {
|
|
|
|
const AbstractType& return_type =
|
|
|
|
AbstractType::Handle(isolate, func.result_type());
|
|
|
|
return TypeToHandle(isolate, "Dart_FunctionReturnType", return_type);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-07-16 22:05:16 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_FunctionParameterCounts(
|
|
|
|
Dart_Handle function,
|
|
|
|
int64_t* fixed_param_count,
|
|
|
|
int64_t* opt_param_count) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
if (fixed_param_count == NULL) {
|
|
|
|
RETURN_NULL_ERROR(fixed_param_count);
|
|
|
|
}
|
|
|
|
if (opt_param_count == NULL) {
|
|
|
|
RETURN_NULL_ERROR(opt_param_count);
|
|
|
|
}
|
|
|
|
const Function& func = Api::UnwrapFunctionHandle(isolate, function);
|
|
|
|
if (func.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, function, Function);
|
|
|
|
}
|
|
|
|
|
|
|
|
// We hide implicit parameters, such as a method's receiver. This is
|
|
|
|
// consistent with Invoke or New, which don't expect their callers to
|
|
|
|
// provide them in the argument lists they are handed.
|
2012-09-12 23:35:05 +00:00
|
|
|
*fixed_param_count = func.num_fixed_parameters() -
|
|
|
|
func.NumImplicitParameters();
|
2012-09-07 01:13:27 +00:00
|
|
|
// TODO(regis): Separately report named and positional optional param counts.
|
2012-09-12 23:35:05 +00:00
|
|
|
*opt_param_count = func.NumOptionalParameters();
|
2012-07-16 22:05:16 +00:00
|
|
|
|
2012-07-26 18:30:40 +00:00
|
|
|
ASSERT(*fixed_param_count >= 0);
|
|
|
|
ASSERT(*opt_param_count >= 0);
|
|
|
|
|
2012-07-16 22:05:16 +00:00
|
|
|
return Api::Success(isolate);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-13 17:47:25 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_FunctionParameterType(Dart_Handle function,
|
|
|
|
int parameter_index) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
const Function& func = Api::UnwrapFunctionHandle(isolate, function);
|
|
|
|
if (func.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, function, Function);
|
|
|
|
}
|
|
|
|
|
|
|
|
const intptr_t num_implicit_params = func.NumImplicitParameters();
|
|
|
|
const intptr_t num_params = func.NumParameters() - num_implicit_params;
|
|
|
|
if (parameter_index < 0 || parameter_index >= num_params) {
|
|
|
|
return Api::NewError(
|
|
|
|
"%s: argument 'parameter_index' out of range. "
|
|
|
|
"Expected 0..%"Pd" but saw %d.",
|
|
|
|
CURRENT_FUNC, num_params, parameter_index);
|
|
|
|
}
|
|
|
|
const AbstractType& param_type =
|
|
|
|
AbstractType::Handle(isolate, func.ParameterTypeAt(
|
|
|
|
num_implicit_params + parameter_index));
|
|
|
|
return TypeToHandle(isolate, "Dart_FunctionParameterType", param_type);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-07-09 23:57:08 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_GetVariableNames(Dart_Handle target) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(target));
|
|
|
|
if (obj.IsError()) {
|
|
|
|
return target;
|
|
|
|
}
|
|
|
|
|
|
|
|
const GrowableObjectArray& names =
|
|
|
|
GrowableObjectArray::Handle(isolate, GrowableObjectArray::New());
|
|
|
|
Field& field = Field::Handle(isolate);
|
|
|
|
String& name = String::Handle(isolate);
|
|
|
|
|
|
|
|
if (obj.IsClass()) {
|
|
|
|
const Class& cls = Class::Cast(obj);
|
|
|
|
const Array& field_array = Array::Handle(cls.fields());
|
|
|
|
|
2012-10-12 22:40:24 +00:00
|
|
|
// Some special types like 'dynamic' have a null fields list.
|
2012-07-09 23:57:08 +00:00
|
|
|
//
|
2012-10-12 22:40:24 +00:00
|
|
|
// TODO(turnidge): Fix 'dynamic' so that it does not have a null
|
2012-07-09 23:57:08 +00:00
|
|
|
// fields list. This will have to wait until the empty array is
|
|
|
|
// allocated in the vm isolate.
|
|
|
|
if (!field_array.IsNull()) {
|
|
|
|
for (intptr_t i = 0; i < field_array.Length(); ++i) {
|
|
|
|
field ^= field_array.At(i);
|
2012-08-08 17:22:26 +00:00
|
|
|
name = field.UserVisibleName();
|
2012-07-09 23:57:08 +00:00
|
|
|
names.Add(name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (obj.IsLibrary()) {
|
|
|
|
const Library& lib = Library::Cast(obj);
|
|
|
|
DictionaryIterator it(lib);
|
|
|
|
Object& obj = Object::Handle(isolate);
|
|
|
|
while (it.HasNext()) {
|
|
|
|
obj = it.GetNext();
|
|
|
|
if (obj.IsField()) {
|
|
|
|
field ^= obj.raw();
|
2012-08-08 17:22:26 +00:00
|
|
|
name = field.UserVisibleName();
|
2012-07-09 23:57:08 +00:00
|
|
|
names.Add(name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return Api::NewError(
|
|
|
|
"%s expects argument 'target' to be a class or library.",
|
|
|
|
CURRENT_FUNC);
|
|
|
|
}
|
|
|
|
return Api::NewHandle(isolate, Array::MakeArray(names));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_LookupVariable(Dart_Handle target,
|
|
|
|
Dart_Handle variable_name) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(target));
|
|
|
|
if (obj.IsError()) {
|
|
|
|
return target;
|
|
|
|
}
|
|
|
|
const String& var_name = Api::UnwrapStringHandle(isolate, variable_name);
|
|
|
|
if (var_name.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, variable_name, String);
|
|
|
|
}
|
|
|
|
if (obj.IsClass()) {
|
|
|
|
const Class& cls = Class::Cast(obj);
|
|
|
|
return Api::NewHandle(isolate, cls.LookupField(var_name));
|
|
|
|
}
|
|
|
|
if (obj.IsLibrary()) {
|
|
|
|
const Library& lib = Library::Cast(obj);
|
|
|
|
return Api::NewHandle(isolate, lib.LookupFieldAllowPrivate(var_name));
|
|
|
|
}
|
|
|
|
return Api::NewError(
|
|
|
|
"%s expects argument 'target' to be a class or library.",
|
|
|
|
CURRENT_FUNC);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT bool Dart_IsVariable(Dart_Handle handle) {
|
2012-08-08 19:46:23 +00:00
|
|
|
return Api::ClassId(handle) == kFieldCid;
|
2012-07-09 23:57:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_VariableName(Dart_Handle variable) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
const Field& var = Api::UnwrapFieldHandle(isolate, variable);
|
|
|
|
if (var.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, variable, Field);
|
|
|
|
}
|
2012-08-08 17:22:26 +00:00
|
|
|
return Api::NewHandle(isolate, var.UserVisibleName());
|
2012-07-09 23:57:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_VariableIsStatic(Dart_Handle variable,
|
|
|
|
bool* is_static) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
if (is_static == NULL) {
|
|
|
|
RETURN_NULL_ERROR(is_static);
|
|
|
|
}
|
|
|
|
const Field& var = Api::UnwrapFieldHandle(isolate, variable);
|
|
|
|
if (var.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, variable, Field);
|
|
|
|
}
|
|
|
|
*is_static = var.is_static();
|
|
|
|
return Api::Success(isolate);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_VariableIsFinal(Dart_Handle variable,
|
|
|
|
bool* is_final) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
if (is_final == NULL) {
|
|
|
|
RETURN_NULL_ERROR(is_final);
|
|
|
|
}
|
|
|
|
const Field& var = Api::UnwrapFieldHandle(isolate, variable);
|
|
|
|
if (var.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, variable, Field);
|
|
|
|
}
|
|
|
|
*is_final = var.is_final();
|
|
|
|
return Api::Success(isolate);
|
|
|
|
}
|
|
|
|
|
2012-09-13 17:47:25 +00:00
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_VariableType(Dart_Handle variable) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
const Field& var = Api::UnwrapFieldHandle(isolate, variable);
|
|
|
|
if (var.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, variable, Field);
|
|
|
|
}
|
|
|
|
|
|
|
|
const AbstractType& type = AbstractType::Handle(isolate, var.type());
|
|
|
|
return TypeToHandle(isolate, "Dart_VariableType", type);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_GetTypeVariableNames(Dart_Handle clazz) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
const Class& cls = Api::UnwrapClassHandle(isolate, clazz);
|
|
|
|
if (cls.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, clazz, Class);
|
|
|
|
}
|
|
|
|
|
|
|
|
const intptr_t num_type_params = cls.NumTypeParameters();
|
|
|
|
const TypeArguments& type_params =
|
|
|
|
TypeArguments::Handle(cls.type_parameters());
|
|
|
|
|
|
|
|
const GrowableObjectArray& names =
|
|
|
|
GrowableObjectArray::Handle(isolate, GrowableObjectArray::New());
|
|
|
|
TypeParameter& type_param = TypeParameter::Handle(isolate);
|
|
|
|
String& name = String::Handle(isolate);
|
|
|
|
for (intptr_t i = 0; i < num_type_params; i++) {
|
|
|
|
type_param ^= type_params.TypeAt(i);
|
|
|
|
name = type_param.name();
|
|
|
|
names.Add(name);
|
|
|
|
}
|
|
|
|
return Api::NewHandle(isolate, Array::MakeArray(names));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_LookupTypeVariable(
|
|
|
|
Dart_Handle clazz,
|
|
|
|
Dart_Handle type_variable_name) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
const Class& cls = Api::UnwrapClassHandle(isolate, clazz);
|
|
|
|
if (cls.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, clazz, Class);
|
|
|
|
}
|
|
|
|
const String& var_name = Api::UnwrapStringHandle(isolate, type_variable_name);
|
|
|
|
if (var_name.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, type_variable_name, String);
|
|
|
|
}
|
|
|
|
|
|
|
|
const intptr_t num_type_params = cls.NumTypeParameters();
|
|
|
|
const TypeArguments& type_params =
|
|
|
|
TypeArguments::Handle(cls.type_parameters());
|
|
|
|
|
|
|
|
TypeParameter& type_param = TypeParameter::Handle(isolate);
|
|
|
|
String& name = String::Handle(isolate);
|
|
|
|
for (intptr_t i = 0; i < num_type_params; i++) {
|
|
|
|
type_param ^= type_params.TypeAt(i);
|
|
|
|
name = type_param.name();
|
|
|
|
if (name.Equals(var_name)) {
|
|
|
|
return Api::NewHandle(isolate, type_param.raw());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const String& cls_name = String::Handle(cls.UserVisibleName());
|
|
|
|
return Api::NewError(
|
|
|
|
"%s: Could not find type variable named '%s' for class %s.\n",
|
|
|
|
CURRENT_FUNC, var_name.ToCString(), cls_name.ToCString());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT bool Dart_IsTypeVariable(Dart_Handle handle) {
|
|
|
|
return Api::ClassId(handle) == kTypeParameterCid;
|
|
|
|
}
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_TypeVariableName(Dart_Handle type_variable) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
const TypeParameter& type_var =
|
|
|
|
Api::UnwrapTypeParameterHandle(isolate, type_variable);
|
|
|
|
if (type_var.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, type_variable, TypeParameter);
|
|
|
|
}
|
|
|
|
return Api::NewHandle(isolate, type_var.name());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_TypeVariableOwner(Dart_Handle type_variable) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
const TypeParameter& type_var =
|
|
|
|
Api::UnwrapTypeParameterHandle(isolate, type_variable);
|
|
|
|
if (type_var.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, type_variable, TypeParameter);
|
|
|
|
}
|
|
|
|
const Class& owner = Class::Handle(type_var.parameterized_class());
|
|
|
|
ASSERT(!owner.IsNull() && owner.IsClass());
|
|
|
|
return Api::NewHandle(isolate, owner.raw());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_TypeVariableUpperBound(Dart_Handle type_variable) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
const TypeParameter& type_var =
|
|
|
|
Api::UnwrapTypeParameterHandle(isolate, type_variable);
|
|
|
|
if (type_var.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, type_variable, TypeParameter);
|
|
|
|
}
|
|
|
|
const AbstractType& bound = AbstractType::Handle(type_var.bound());
|
|
|
|
return TypeToHandle(isolate, "Dart_TypeVariableUpperBound", bound);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-04-23 17:36:05 +00:00
|
|
|
// --- Constructors, Methods, and Fields ---
|
|
|
|
|
|
|
|
|
|
|
|
static RawObject* ResolveConstructor(const char* current_func,
|
2012-05-29 18:00:45 +00:00
|
|
|
const Class& cls,
|
|
|
|
const String& class_name,
|
|
|
|
const String& dotted_name,
|
2012-04-23 17:36:05 +00:00
|
|
|
int num_args) {
|
|
|
|
// The constructor must be present in the interface.
|
|
|
|
String& constr_name = String::Handle(String::Concat(class_name, dotted_name));
|
|
|
|
const Function& constructor =
|
|
|
|
Function::Handle(cls.LookupFunction(constr_name));
|
|
|
|
if (constructor.IsNull() ||
|
|
|
|
(!constructor.IsConstructor() && !constructor.IsFactory())) {
|
2012-05-29 18:00:45 +00:00
|
|
|
const String& lookup_class_name = String::Handle(cls.Name());
|
|
|
|
if (!class_name.Equals(lookup_class_name)) {
|
|
|
|
// When the class name used to build the constructor name is
|
|
|
|
// different than the name of the class in which we are doing
|
|
|
|
// the lookup, it can be confusing to the user to figure out
|
|
|
|
// what's going on. Be a little more explicit for these error
|
|
|
|
// messages.
|
|
|
|
const String& message = String::Handle(
|
|
|
|
String::NewFormatted(
|
|
|
|
"%s: could not find factory '%s' in class '%s'.",
|
|
|
|
current_func,
|
|
|
|
constr_name.ToCString(),
|
|
|
|
lookup_class_name.ToCString()));
|
|
|
|
return ApiError::New(message);
|
|
|
|
} else {
|
|
|
|
const String& message = String::Handle(
|
|
|
|
String::NewFormatted("%s: could not find constructor '%s'.",
|
|
|
|
current_func, constr_name.ToCString()));
|
|
|
|
return ApiError::New(message);
|
|
|
|
}
|
2012-04-23 17:36:05 +00:00
|
|
|
}
|
|
|
|
int extra_args = (constructor.IsConstructor() ? 2 : 1);
|
2012-07-12 17:46:55 +00:00
|
|
|
String& error_message = String::Handle();
|
|
|
|
if (!constructor.AreValidArgumentCounts(num_args + extra_args,
|
|
|
|
0,
|
|
|
|
&error_message)) {
|
2012-04-23 17:36:05 +00:00
|
|
|
const String& message = String::Handle(
|
2012-07-12 17:46:55 +00:00
|
|
|
String::NewFormatted("%s: wrong argument count for "
|
|
|
|
"constructor '%s': %s.",
|
2012-04-23 17:36:05 +00:00
|
|
|
current_func,
|
|
|
|
constr_name.ToCString(),
|
2012-07-12 17:46:55 +00:00
|
|
|
error_message.ToCString()));
|
2012-04-23 17:36:05 +00:00
|
|
|
return ApiError::New(message);
|
|
|
|
}
|
|
|
|
return constructor.raw();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_New(Dart_Handle clazz,
|
|
|
|
Dart_Handle constructor_name,
|
|
|
|
int number_of_arguments,
|
|
|
|
Dart_Handle* arguments) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
Object& result = Object::Handle(isolate);
|
|
|
|
|
|
|
|
if (number_of_arguments < 0) {
|
|
|
|
return Api::NewError(
|
|
|
|
"%s expects argument 'number_of_arguments' to be non-negative.",
|
|
|
|
CURRENT_FUNC);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the class to instantiate.
|
2012-08-22 13:42:06 +00:00
|
|
|
Class& cls =
|
|
|
|
Class::Handle(isolate, Api::UnwrapClassHandle(isolate, clazz).raw());
|
2012-04-23 17:36:05 +00:00
|
|
|
if (cls.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, clazz, Class);
|
|
|
|
}
|
2012-05-29 18:00:45 +00:00
|
|
|
String& base_constructor_name = String::Handle();
|
|
|
|
base_constructor_name = cls.Name();
|
2012-04-23 17:36:05 +00:00
|
|
|
|
|
|
|
// And get the name of the constructor to invoke.
|
|
|
|
String& dot_name = String::Handle(isolate);
|
|
|
|
const Object& name_obj =
|
|
|
|
Object::Handle(isolate, Api::UnwrapHandle(constructor_name));
|
|
|
|
if (name_obj.IsNull()) {
|
2012-07-24 00:01:50 +00:00
|
|
|
dot_name = Symbols::Dot();
|
2012-04-23 17:36:05 +00:00
|
|
|
} else if (name_obj.IsString()) {
|
2012-12-10 18:24:34 +00:00
|
|
|
dot_name = String::Concat(Symbols::DotHandle(), String::Cast(name_obj));
|
2012-04-23 17:36:05 +00:00
|
|
|
} else {
|
2012-08-22 13:42:06 +00:00
|
|
|
RETURN_TYPE_ERROR(isolate, constructor_name, String);
|
2012-04-23 17:36:05 +00:00
|
|
|
}
|
|
|
|
const char* msg = CheckIsolateState(isolate);
|
|
|
|
if (msg != NULL) {
|
2012-09-06 00:58:25 +00:00
|
|
|
return Api::NewError("%s", msg);
|
2012-04-23 17:36:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Resolve the constructor.
|
2012-05-29 18:00:45 +00:00
|
|
|
result = ResolveConstructor(
|
|
|
|
"Dart_New", cls, base_constructor_name, dot_name, number_of_arguments);
|
2012-04-23 17:36:05 +00:00
|
|
|
if (result.IsError()) {
|
|
|
|
return Api::NewHandle(isolate, result.raw());
|
|
|
|
}
|
2012-11-28 23:39:27 +00:00
|
|
|
// TODO(turnidge): Support redirecting factories.
|
2012-04-23 17:36:05 +00:00
|
|
|
ASSERT(result.IsFunction());
|
|
|
|
Function& constructor = Function::Handle(isolate);
|
|
|
|
constructor ^= result.raw();
|
|
|
|
|
|
|
|
Instance& new_object = Instance::Handle(isolate);
|
|
|
|
if (constructor.IsConstructor()) {
|
|
|
|
// Create the new object.
|
|
|
|
new_object = Instance::New(cls);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create the argument list.
|
|
|
|
int extra_args = (constructor.IsConstructor() ? 2 : 1);
|
|
|
|
GrowableArray<const Object*> args(number_of_arguments + extra_args);
|
|
|
|
if (constructor.IsConstructor()) {
|
2012-05-29 18:00:45 +00:00
|
|
|
// Constructors get the uninitialized object and a constructor phase.
|
2012-04-23 17:36:05 +00:00
|
|
|
args.Add(&new_object);
|
2012-05-29 18:00:45 +00:00
|
|
|
args.Add(&Smi::Handle(isolate, Smi::New(Function::kCtorPhaseAll)));
|
|
|
|
} else {
|
|
|
|
// Factories get type arguments.
|
|
|
|
args.Add(&TypeArguments::Handle(isolate));
|
2012-04-23 17:36:05 +00:00
|
|
|
}
|
|
|
|
for (int i = 0; i < number_of_arguments; i++) {
|
|
|
|
const Object& arg =
|
|
|
|
Object::Handle(isolate, Api::UnwrapHandle(arguments[i]));
|
|
|
|
if (!arg.IsNull() && !arg.IsInstance()) {
|
|
|
|
if (arg.IsError()) {
|
|
|
|
return Api::NewHandle(isolate, arg.raw());
|
|
|
|
} else {
|
|
|
|
return Api::NewError(
|
2012-06-12 21:07:49 +00:00
|
|
|
"%s expects arguments[%d] to be an Instance handle.",
|
2012-04-23 17:36:05 +00:00
|
|
|
CURRENT_FUNC, i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
args.Add(&arg);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Invoke the constructor and return the new object.
|
|
|
|
const Array& kNoArgNames = Array::Handle(isolate);
|
|
|
|
result = DartEntry::InvokeStatic(constructor, args, kNoArgNames);
|
|
|
|
if (result.IsError()) {
|
|
|
|
return Api::NewHandle(isolate, result.raw());
|
|
|
|
}
|
|
|
|
if (constructor.IsConstructor()) {
|
|
|
|
ASSERT(result.IsNull());
|
|
|
|
} else {
|
|
|
|
ASSERT(result.IsNull() || result.IsInstance());
|
|
|
|
new_object ^= result.raw();
|
|
|
|
}
|
|
|
|
return Api::NewHandle(isolate, new_object.raw());
|
|
|
|
}
|
2011-11-22 19:42:38 +00:00
|
|
|
|
|
|
|
|
2012-03-13 19:49:48 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_Invoke(Dart_Handle target,
|
|
|
|
Dart_Handle name,
|
|
|
|
int number_of_arguments,
|
|
|
|
Dart_Handle* arguments) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
|
2012-04-04 20:31:49 +00:00
|
|
|
const String& function_name = Api::UnwrapStringHandle(isolate, name);
|
2012-03-13 19:49:48 +00:00
|
|
|
if (function_name.IsNull()) {
|
2012-04-04 20:31:49 +00:00
|
|
|
RETURN_TYPE_ERROR(isolate, name, String);
|
2012-03-13 19:49:48 +00:00
|
|
|
}
|
|
|
|
if (number_of_arguments < 0) {
|
|
|
|
return Api::NewError(
|
|
|
|
"%s expects argument 'number_of_arguments' to be non-negative.",
|
|
|
|
CURRENT_FUNC);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check for malformed arguments in the arguments list.
|
2012-04-23 17:36:05 +00:00
|
|
|
GrowableArray<const Object*> args(number_of_arguments);
|
2012-03-13 19:49:48 +00:00
|
|
|
for (int i = 0; i < number_of_arguments; i++) {
|
2012-04-04 20:31:49 +00:00
|
|
|
const Object& arg =
|
|
|
|
Object::Handle(isolate, Api::UnwrapHandle(arguments[i]));
|
2012-03-13 19:49:48 +00:00
|
|
|
if (!arg.IsNull() && !arg.IsInstance()) {
|
|
|
|
if (arg.IsError()) {
|
2012-04-06 17:05:50 +00:00
|
|
|
return Api::NewHandle(isolate, arg.raw());
|
2012-03-13 19:49:48 +00:00
|
|
|
} else {
|
|
|
|
return Api::NewError(
|
2012-06-12 21:07:49 +00:00
|
|
|
"%s expects arguments[%d] to be an Instance handle.",
|
2012-03-13 19:49:48 +00:00
|
|
|
CURRENT_FUNC, i);
|
|
|
|
}
|
|
|
|
}
|
2012-04-23 17:36:05 +00:00
|
|
|
args.Add(&arg);
|
2012-03-13 19:49:48 +00:00
|
|
|
}
|
|
|
|
|
2012-04-04 20:31:49 +00:00
|
|
|
const Array& kNoArgNames = Array::Handle(isolate);
|
|
|
|
const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(target));
|
2012-05-30 17:07:19 +00:00
|
|
|
if (obj.IsError()) {
|
|
|
|
return target;
|
|
|
|
}
|
|
|
|
|
2012-04-19 21:04:15 +00:00
|
|
|
if (obj.IsNull() || obj.IsInstance()) {
|
2012-04-04 20:31:49 +00:00
|
|
|
Instance& instance = Instance::Handle(isolate);
|
2012-03-13 19:49:48 +00:00
|
|
|
instance ^= obj.raw();
|
|
|
|
const Function& function = Function::Handle(
|
2012-04-04 20:31:49 +00:00
|
|
|
isolate,
|
2012-03-13 19:49:48 +00:00
|
|
|
Resolver::ResolveDynamic(instance,
|
|
|
|
function_name,
|
|
|
|
(number_of_arguments + 1),
|
|
|
|
Resolver::kIsQualified));
|
2012-04-19 21:04:15 +00:00
|
|
|
// TODO(5415268): Invoke noSuchMethod instead of failing.
|
2012-03-13 19:49:48 +00:00
|
|
|
if (function.IsNull()) {
|
2012-04-04 20:31:49 +00:00
|
|
|
const Type& type = Type::Handle(isolate, instance.GetType());
|
|
|
|
const String& cls_name = String::Handle(isolate, type.ClassName());
|
2012-03-13 19:49:48 +00:00
|
|
|
return Api::NewError("%s: did not find instance method '%s.%s'.",
|
|
|
|
CURRENT_FUNC,
|
|
|
|
cls_name.ToCString(),
|
|
|
|
function_name.ToCString());
|
|
|
|
}
|
2012-04-06 17:05:50 +00:00
|
|
|
return Api::NewHandle(
|
2012-04-04 20:31:49 +00:00
|
|
|
isolate,
|
2012-04-23 17:36:05 +00:00
|
|
|
DartEntry::InvokeDynamic(instance, function, args, kNoArgNames));
|
2012-03-13 19:49:48 +00:00
|
|
|
|
|
|
|
} else if (obj.IsClass()) {
|
|
|
|
// Finalize all classes.
|
|
|
|
const char* msg = CheckIsolateState(isolate);
|
|
|
|
if (msg != NULL) {
|
2012-09-06 00:58:25 +00:00
|
|
|
return Api::NewError("%s", msg);
|
2012-03-13 19:49:48 +00:00
|
|
|
}
|
|
|
|
|
2012-07-02 21:42:53 +00:00
|
|
|
const Class& cls = Class::Cast(obj);
|
2012-03-13 19:49:48 +00:00
|
|
|
const Function& function = Function::Handle(
|
2012-04-04 20:31:49 +00:00
|
|
|
isolate,
|
2012-03-13 19:49:48 +00:00
|
|
|
Resolver::ResolveStatic(cls,
|
|
|
|
function_name,
|
|
|
|
number_of_arguments,
|
2012-04-04 20:31:49 +00:00
|
|
|
Array::Handle(isolate),
|
2012-03-13 19:49:48 +00:00
|
|
|
Resolver::kIsQualified));
|
|
|
|
if (function.IsNull()) {
|
2012-04-04 20:31:49 +00:00
|
|
|
const String& cls_name = String::Handle(isolate, cls.Name());
|
2012-03-13 19:49:48 +00:00
|
|
|
return Api::NewError("%s: did not find static method '%s.%s'.",
|
|
|
|
CURRENT_FUNC,
|
|
|
|
cls_name.ToCString(),
|
|
|
|
function_name.ToCString());
|
|
|
|
}
|
2012-04-06 17:05:50 +00:00
|
|
|
return Api::NewHandle(
|
2012-04-04 20:31:49 +00:00
|
|
|
isolate,
|
2012-04-23 17:36:05 +00:00
|
|
|
DartEntry::InvokeStatic(function, args, kNoArgNames));
|
2012-03-13 19:49:48 +00:00
|
|
|
|
|
|
|
} else if (obj.IsLibrary()) {
|
2012-03-28 01:21:04 +00:00
|
|
|
// Check whether class finalization is needed.
|
|
|
|
bool finalize_classes = true;
|
2012-07-02 21:42:53 +00:00
|
|
|
const Library& lib = Library::Cast(obj);
|
2012-03-28 01:21:04 +00:00
|
|
|
|
|
|
|
// When calling functions in the dart:builtin library do not finalize as it
|
|
|
|
// should have been prefinalized.
|
|
|
|
Library& builtin =
|
2012-04-04 20:31:49 +00:00
|
|
|
Library::Handle(isolate, isolate->object_store()->builtin_library());
|
2012-03-28 01:21:04 +00:00
|
|
|
if (builtin.raw() == lib.raw()) {
|
|
|
|
finalize_classes = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Finalize all classes if needed.
|
|
|
|
if (finalize_classes) {
|
|
|
|
const char* msg = CheckIsolateState(isolate);
|
|
|
|
if (msg != NULL) {
|
2012-09-06 00:58:25 +00:00
|
|
|
return Api::NewError("%s", msg);
|
2012-03-28 01:21:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-04-18 18:11:55 +00:00
|
|
|
Function& function = Function::Handle(isolate);
|
2012-04-19 21:04:15 +00:00
|
|
|
function = lib.LookupFunctionAllowPrivate(function_name);
|
2012-03-13 19:49:48 +00:00
|
|
|
if (function.IsNull()) {
|
|
|
|
return Api::NewError("%s: did not find top-level function '%s'.",
|
|
|
|
CURRENT_FUNC,
|
|
|
|
function_name.ToCString());
|
|
|
|
}
|
2012-07-12 17:46:55 +00:00
|
|
|
// LookupFunctionAllowPrivate does not check argument arity, so we
|
|
|
|
// do it here.
|
|
|
|
String& error_message = String::Handle();
|
|
|
|
if (!function.AreValidArgumentCounts(number_of_arguments,
|
|
|
|
0,
|
|
|
|
&error_message)) {
|
|
|
|
return Api::NewError("%s: wrong argument count for function '%s': %s.",
|
|
|
|
CURRENT_FUNC,
|
|
|
|
function_name.ToCString(),
|
|
|
|
error_message.ToCString());
|
|
|
|
}
|
2012-04-06 17:05:50 +00:00
|
|
|
return Api::NewHandle(
|
2012-04-23 17:36:05 +00:00
|
|
|
isolate, DartEntry::InvokeStatic(function, args, kNoArgNames));
|
2012-03-13 19:49:48 +00:00
|
|
|
|
|
|
|
} else {
|
|
|
|
return Api::NewError(
|
|
|
|
"%s expects argument 'target' to be an object, class, or library.",
|
|
|
|
CURRENT_FUNC);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-04-04 20:31:49 +00:00
|
|
|
static bool FieldIsUninitialized(Isolate* isolate, const Field& fld) {
|
2012-03-07 21:15:58 +00:00
|
|
|
ASSERT(!fld.IsNull());
|
2011-10-05 05:20:07 +00:00
|
|
|
|
|
|
|
// Return getter method for uninitialized fields, rather than the
|
|
|
|
// field object, since the value in the field object will not be
|
|
|
|
// initialized until the first time the getter is invoked.
|
2012-04-04 20:31:49 +00:00
|
|
|
const Instance& value = Instance::Handle(isolate, fld.value());
|
2011-10-05 05:20:07 +00:00
|
|
|
ASSERT(value.raw() != Object::transition_sentinel());
|
|
|
|
return value.raw() == Object::sentinel();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-03-07 21:15:58 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_GetField(Dart_Handle container, Dart_Handle name) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
|
2012-04-04 20:31:49 +00:00
|
|
|
const String& field_name = Api::UnwrapStringHandle(isolate, name);
|
2012-03-07 21:15:58 +00:00
|
|
|
if (field_name.IsNull()) {
|
2012-04-04 20:31:49 +00:00
|
|
|
RETURN_TYPE_ERROR(isolate, name, String);
|
2012-03-07 21:15:58 +00:00
|
|
|
}
|
|
|
|
|
2012-04-04 20:31:49 +00:00
|
|
|
const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(container));
|
2012-03-07 21:15:58 +00:00
|
|
|
|
2012-04-04 20:31:49 +00:00
|
|
|
Field& field = Field::Handle(isolate);
|
|
|
|
Function& getter = Function::Handle(isolate);
|
2012-03-07 21:15:58 +00:00
|
|
|
if (obj.IsNull()) {
|
|
|
|
return Api::NewError("%s expects argument 'container' to be non-null.",
|
|
|
|
CURRENT_FUNC);
|
|
|
|
} else if (obj.IsInstance()) {
|
|
|
|
// Every instance field has a getter Function. Try to find the
|
|
|
|
// getter in any superclass and use that function to access the
|
|
|
|
// field.
|
2012-07-02 21:42:53 +00:00
|
|
|
const Instance& instance = Instance::Cast(obj);
|
2012-04-04 20:31:49 +00:00
|
|
|
Class& cls = Class::Handle(isolate, instance.clazz());
|
2012-03-07 21:15:58 +00:00
|
|
|
while (!cls.IsNull()) {
|
2012-04-04 20:31:49 +00:00
|
|
|
String& getter_name =
|
|
|
|
String::Handle(isolate, Field::GetterName(field_name));
|
2012-03-07 21:15:58 +00:00
|
|
|
getter = cls.LookupDynamicFunction(getter_name);
|
|
|
|
if (!getter.IsNull()) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
cls = cls.SuperClass();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (getter.IsNull()) {
|
|
|
|
return Api::NewError("%s: did not find instance field '%s'.",
|
|
|
|
CURRENT_FUNC, field_name.ToCString());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Invoke the getter and return the result.
|
|
|
|
GrowableArray<const Object*> args;
|
2012-04-04 20:31:49 +00:00
|
|
|
const Array& kNoArgNames = Array::Handle(isolate);
|
2012-04-06 17:05:50 +00:00
|
|
|
return Api::NewHandle(
|
2012-04-04 20:31:49 +00:00
|
|
|
isolate,
|
2012-03-07 21:15:58 +00:00
|
|
|
DartEntry::InvokeDynamic(instance, getter, args, kNoArgNames));
|
|
|
|
|
|
|
|
} else if (obj.IsClass()) {
|
2012-05-23 21:54:00 +00:00
|
|
|
// Finalize all classes.
|
|
|
|
const char* msg = CheckIsolateState(isolate);
|
|
|
|
if (msg != NULL) {
|
2012-09-06 00:58:25 +00:00
|
|
|
return Api::NewError("%s", msg);
|
2012-05-23 21:54:00 +00:00
|
|
|
}
|
2012-03-07 21:15:58 +00:00
|
|
|
// To access a static field we may need to use the Field or the
|
|
|
|
// getter Function.
|
2012-07-02 21:42:53 +00:00
|
|
|
const Class& cls = Class::Cast(obj);
|
2012-03-07 21:15:58 +00:00
|
|
|
field = cls.LookupStaticField(field_name);
|
2012-04-04 20:31:49 +00:00
|
|
|
if (field.IsNull() || FieldIsUninitialized(isolate, field)) {
|
|
|
|
const String& getter_name =
|
|
|
|
String::Handle(isolate, Field::GetterName(field_name));
|
2012-03-07 21:15:58 +00:00
|
|
|
getter = cls.LookupStaticFunction(getter_name);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!getter.IsNull()) {
|
|
|
|
// Invoke the getter and return the result.
|
|
|
|
GrowableArray<const Object*> args;
|
2012-04-04 20:31:49 +00:00
|
|
|
const Array& kNoArgNames = Array::Handle(isolate);
|
2012-04-06 17:05:50 +00:00
|
|
|
return Api::NewHandle(
|
2012-04-04 20:31:49 +00:00
|
|
|
isolate, DartEntry::InvokeStatic(getter, args, kNoArgNames));
|
2012-03-07 21:15:58 +00:00
|
|
|
} else if (!field.IsNull()) {
|
2012-04-06 17:05:50 +00:00
|
|
|
return Api::NewHandle(isolate, field.value());
|
2012-03-07 21:15:58 +00:00
|
|
|
} else {
|
|
|
|
return Api::NewError("%s: did not find static field '%s'.",
|
|
|
|
CURRENT_FUNC, field_name.ToCString());
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if (obj.IsLibrary()) {
|
2012-05-23 21:54:00 +00:00
|
|
|
// TODO(turnidge): Do we need to call CheckIsolateState here?
|
|
|
|
|
2012-03-07 21:15:58 +00:00
|
|
|
// To access a top-level we may need to use the Field or the
|
|
|
|
// getter Function. The getter function may either be in the
|
|
|
|
// library or in the field's owner class, depending.
|
2012-07-02 21:42:53 +00:00
|
|
|
const Library& lib = Library::Cast(obj);
|
2012-04-19 21:04:15 +00:00
|
|
|
field = lib.LookupFieldAllowPrivate(field_name);
|
2012-03-07 21:15:58 +00:00
|
|
|
if (field.IsNull()) {
|
|
|
|
// No field found. Check for a getter in the lib.
|
2012-04-04 20:31:49 +00:00
|
|
|
const String& getter_name =
|
|
|
|
String::Handle(isolate, Field::GetterName(field_name));
|
2012-04-19 21:04:15 +00:00
|
|
|
getter = lib.LookupFunctionAllowPrivate(getter_name);
|
2012-04-04 20:31:49 +00:00
|
|
|
} else if (FieldIsUninitialized(isolate, field)) {
|
2012-03-07 21:15:58 +00:00
|
|
|
// A field was found. Check for a getter in the field's owner classs.
|
2012-04-04 20:31:49 +00:00
|
|
|
const Class& cls = Class::Handle(isolate, field.owner());
|
|
|
|
const String& getter_name =
|
|
|
|
String::Handle(isolate, Field::GetterName(field_name));
|
2012-03-07 21:15:58 +00:00
|
|
|
getter = cls.LookupStaticFunction(getter_name);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!getter.IsNull()) {
|
|
|
|
// Invoke the getter and return the result.
|
|
|
|
GrowableArray<const Object*> args;
|
2012-04-04 20:31:49 +00:00
|
|
|
const Array& kNoArgNames = Array::Handle(isolate);
|
2012-04-06 17:05:50 +00:00
|
|
|
return Api::NewHandle(
|
2012-04-04 20:31:49 +00:00
|
|
|
isolate, DartEntry::InvokeStatic(getter, args, kNoArgNames));
|
2012-03-07 21:15:58 +00:00
|
|
|
} else if (!field.IsNull()) {
|
2012-04-06 17:05:50 +00:00
|
|
|
return Api::NewHandle(isolate, field.value());
|
2012-03-07 21:15:58 +00:00
|
|
|
} else {
|
|
|
|
return Api::NewError("%s: did not find top-level variable '%s'.",
|
|
|
|
CURRENT_FUNC, field_name.ToCString());
|
|
|
|
}
|
|
|
|
|
2012-08-22 13:42:06 +00:00
|
|
|
} else if (obj.IsError()) {
|
|
|
|
return container;
|
2012-03-07 21:15:58 +00:00
|
|
|
} else {
|
|
|
|
return Api::NewError(
|
|
|
|
"%s expects argument 'container' to be an object, class, or library.",
|
|
|
|
CURRENT_FUNC);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_SetField(Dart_Handle container,
|
|
|
|
Dart_Handle name,
|
|
|
|
Dart_Handle value) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
|
2012-04-04 20:31:49 +00:00
|
|
|
const String& field_name = Api::UnwrapStringHandle(isolate, name);
|
2012-03-07 21:15:58 +00:00
|
|
|
if (field_name.IsNull()) {
|
2012-04-04 20:31:49 +00:00
|
|
|
RETURN_TYPE_ERROR(isolate, name, String);
|
2012-03-07 21:15:58 +00:00
|
|
|
}
|
2012-03-13 19:49:48 +00:00
|
|
|
|
|
|
|
// Since null is allowed for value, we don't use UnwrapInstanceHandle.
|
2012-04-04 20:31:49 +00:00
|
|
|
const Object& value_obj = Object::Handle(isolate, Api::UnwrapHandle(value));
|
2012-03-13 19:49:48 +00:00
|
|
|
if (!value_obj.IsNull() && !value_obj.IsInstance()) {
|
2012-04-04 20:31:49 +00:00
|
|
|
RETURN_TYPE_ERROR(isolate, value, Instance);
|
2012-03-07 21:15:58 +00:00
|
|
|
}
|
2012-04-04 20:31:49 +00:00
|
|
|
Instance& value_instance = Instance::Handle(isolate);
|
2012-03-13 19:49:48 +00:00
|
|
|
value_instance ^= value_obj.raw();
|
2012-03-07 21:15:58 +00:00
|
|
|
|
2012-04-04 20:31:49 +00:00
|
|
|
Field& field = Field::Handle(isolate);
|
|
|
|
Function& setter = Function::Handle(isolate);
|
|
|
|
const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(container));
|
2012-03-07 21:15:58 +00:00
|
|
|
if (obj.IsNull()) {
|
|
|
|
return Api::NewError("%s expects argument 'container' to be non-null.",
|
|
|
|
CURRENT_FUNC);
|
|
|
|
} else if (obj.IsInstance()) {
|
|
|
|
// Every instance field has a setter Function. Try to find the
|
|
|
|
// setter in any superclass and use that function to access the
|
|
|
|
// field.
|
2012-07-02 21:42:53 +00:00
|
|
|
const Instance& instance = Instance::Cast(obj);
|
2012-04-04 20:31:49 +00:00
|
|
|
Class& cls = Class::Handle(isolate, instance.clazz());
|
2012-03-07 21:15:58 +00:00
|
|
|
while (!cls.IsNull()) {
|
|
|
|
field = cls.LookupInstanceField(field_name);
|
|
|
|
if (!field.IsNull() && field.is_final()) {
|
|
|
|
return Api::NewError("%s: cannot set final field '%s'.",
|
|
|
|
CURRENT_FUNC, field_name.ToCString());
|
|
|
|
}
|
2012-04-04 20:31:49 +00:00
|
|
|
String& setter_name =
|
|
|
|
String::Handle(isolate, Field::SetterName(field_name));
|
2012-03-07 21:15:58 +00:00
|
|
|
setter = cls.LookupDynamicFunction(setter_name);
|
|
|
|
if (!setter.IsNull()) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
cls = cls.SuperClass();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (setter.IsNull()) {
|
|
|
|
return Api::NewError("%s: did not find instance field '%s'.",
|
|
|
|
CURRENT_FUNC, field_name.ToCString());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Invoke the setter and return the result.
|
|
|
|
GrowableArray<const Object*> args(1);
|
|
|
|
args.Add(&value_instance);
|
2012-04-04 20:31:49 +00:00
|
|
|
const Array& kNoArgNames = Array::Handle(isolate);
|
2012-04-06 17:05:50 +00:00
|
|
|
return Api::NewHandle(
|
2012-04-04 20:31:49 +00:00
|
|
|
isolate,
|
2012-03-07 21:15:58 +00:00
|
|
|
DartEntry::InvokeDynamic(instance, setter, args, kNoArgNames));
|
|
|
|
|
|
|
|
} else if (obj.IsClass()) {
|
|
|
|
// To access a static field we may need to use the Field or the
|
|
|
|
// setter Function.
|
2012-07-02 21:42:53 +00:00
|
|
|
const Class& cls = Class::Cast(obj);
|
2012-03-07 21:15:58 +00:00
|
|
|
field = cls.LookupStaticField(field_name);
|
|
|
|
if (field.IsNull()) {
|
2012-04-04 20:31:49 +00:00
|
|
|
String& setter_name =
|
|
|
|
String::Handle(isolate, Field::SetterName(field_name));
|
2012-03-07 21:15:58 +00:00
|
|
|
setter = cls.LookupStaticFunction(setter_name);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!setter.IsNull()) {
|
|
|
|
// Invoke the setter and return the result.
|
|
|
|
GrowableArray<const Object*> args(1);
|
|
|
|
args.Add(&value_instance);
|
2012-04-04 20:31:49 +00:00
|
|
|
const Array& kNoArgNames = Array::Handle(isolate);
|
2012-03-07 21:15:58 +00:00
|
|
|
const Object& result = Object::Handle(
|
2012-04-04 20:31:49 +00:00
|
|
|
isolate,
|
2012-03-07 21:15:58 +00:00
|
|
|
DartEntry::InvokeStatic(setter, args, kNoArgNames));
|
|
|
|
if (result.IsError()) {
|
2012-04-06 17:05:50 +00:00
|
|
|
return Api::NewHandle(isolate, result.raw());
|
2012-03-07 21:15:58 +00:00
|
|
|
} else {
|
2012-04-04 20:31:49 +00:00
|
|
|
return Api::Success(isolate);
|
2012-03-07 21:15:58 +00:00
|
|
|
}
|
|
|
|
} else if (!field.IsNull()) {
|
|
|
|
if (field.is_final()) {
|
|
|
|
return Api::NewError("%s: cannot set final field '%s'.",
|
|
|
|
CURRENT_FUNC, field_name.ToCString());
|
|
|
|
} else {
|
|
|
|
field.set_value(value_instance);
|
2012-04-04 20:31:49 +00:00
|
|
|
return Api::Success(isolate);
|
2012-03-07 21:15:58 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return Api::NewError("%s: did not find static field '%s'.",
|
|
|
|
CURRENT_FUNC, field_name.ToCString());
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if (obj.IsLibrary()) {
|
|
|
|
// To access a top-level we may need to use the Field or the
|
|
|
|
// setter Function. The setter function may either be in the
|
|
|
|
// library or in the field's owner class, depending.
|
2012-07-02 21:42:53 +00:00
|
|
|
const Library& lib = Library::Cast(obj);
|
2012-04-19 21:04:15 +00:00
|
|
|
field = lib.LookupFieldAllowPrivate(field_name);
|
2012-03-07 21:15:58 +00:00
|
|
|
if (field.IsNull()) {
|
2012-04-04 20:31:49 +00:00
|
|
|
const String& setter_name =
|
|
|
|
String::Handle(isolate, Field::SetterName(field_name));
|
2012-04-19 21:04:15 +00:00
|
|
|
setter ^= lib.LookupFunctionAllowPrivate(setter_name);
|
2012-03-07 21:15:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!setter.IsNull()) {
|
|
|
|
// Invoke the setter and return the result.
|
|
|
|
GrowableArray<const Object*> args(1);
|
|
|
|
args.Add(&value_instance);
|
2012-04-04 20:31:49 +00:00
|
|
|
const Array& kNoArgNames = Array::Handle(isolate);
|
2012-03-07 21:15:58 +00:00
|
|
|
const Object& result = Object::Handle(
|
2012-04-04 20:31:49 +00:00
|
|
|
isolate, DartEntry::InvokeStatic(setter, args, kNoArgNames));
|
2012-03-07 21:15:58 +00:00
|
|
|
if (result.IsError()) {
|
2012-04-06 17:05:50 +00:00
|
|
|
return Api::NewHandle(isolate, result.raw());
|
2012-03-07 21:15:58 +00:00
|
|
|
} else {
|
2012-04-04 20:31:49 +00:00
|
|
|
return Api::Success(isolate);
|
2012-03-07 21:15:58 +00:00
|
|
|
}
|
|
|
|
} else if (!field.IsNull()) {
|
|
|
|
if (field.is_final()) {
|
|
|
|
return Api::NewError("%s: cannot set final top-level variable '%s'.",
|
|
|
|
CURRENT_FUNC, field_name.ToCString());
|
|
|
|
} else {
|
|
|
|
field.set_value(value_instance);
|
2012-04-04 20:31:49 +00:00
|
|
|
return Api::Success(isolate);
|
2012-03-07 21:15:58 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return Api::NewError("%s: did not find top-level variable '%s'.",
|
|
|
|
CURRENT_FUNC, field_name.ToCString());
|
|
|
|
}
|
|
|
|
|
2012-08-22 13:42:06 +00:00
|
|
|
} else if (obj.IsError()) {
|
|
|
|
return container;
|
2012-03-07 21:15:58 +00:00
|
|
|
} else {
|
|
|
|
return Api::NewError(
|
|
|
|
"%s expects argument 'container' to be an object, class, or library.",
|
|
|
|
CURRENT_FUNC);
|
|
|
|
}
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-10-26 20:38:41 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_CreateNativeWrapperClass(Dart_Handle library,
|
2011-10-05 05:20:07 +00:00
|
|
|
Dart_Handle name,
|
|
|
|
int field_count) {
|
2011-11-12 05:55:22 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
2012-08-22 13:42:06 +00:00
|
|
|
const String& cls_name = Api::UnwrapStringHandle(isolate, name);
|
|
|
|
if (cls_name.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, name, String);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
2012-08-22 13:42:06 +00:00
|
|
|
const Library& lib = Api::UnwrapLibraryHandle(isolate, library);
|
2011-10-05 05:20:07 +00:00
|
|
|
if (lib.IsNull()) {
|
2012-08-22 13:42:06 +00:00
|
|
|
RETURN_TYPE_ERROR(isolate, library, Library);
|
|
|
|
}
|
|
|
|
if (field_count <= 0) {
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError(
|
2012-08-22 13:42:06 +00:00
|
|
|
"Negative field_count passed to Dart_CreateNativeWrapperClass");
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
2012-08-22 13:42:06 +00:00
|
|
|
|
|
|
|
String& cls_symbol = String::Handle(isolate, Symbols::New(cls_name));
|
2012-04-04 20:31:49 +00:00
|
|
|
const Class& cls = Class::Handle(
|
2012-08-22 13:42:06 +00:00
|
|
|
isolate, Class::NewNativeWrapper(lib, cls_symbol, field_count));
|
2011-10-05 05:20:07 +00:00
|
|
|
if (cls.IsNull()) {
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError(
|
2011-10-26 20:38:41 +00:00
|
|
|
"Unable to create native wrapper class : already exists");
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
2012-04-06 17:05:50 +00:00
|
|
|
return Api::NewHandle(isolate, cls.raw());
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-05-30 17:07:19 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_GetNativeInstanceFieldCount(Dart_Handle obj,
|
|
|
|
int* count) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
const Instance& instance = Api::UnwrapInstanceHandle(isolate, obj);
|
|
|
|
if (instance.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, obj, Instance);
|
|
|
|
}
|
|
|
|
const Class& cls = Class::Handle(isolate, instance.clazz());
|
|
|
|
*count = cls.num_native_fields();
|
|
|
|
return Api::Success(isolate);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-10-26 20:38:41 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_GetNativeInstanceField(Dart_Handle obj,
|
|
|
|
int index,
|
|
|
|
intptr_t* value) {
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
2012-05-30 17:07:19 +00:00
|
|
|
const Instance& instance = Api::UnwrapInstanceHandle(isolate, obj);
|
|
|
|
if (instance.IsNull()) {
|
2012-05-21 21:41:49 +00:00
|
|
|
RETURN_TYPE_ERROR(isolate, obj, Instance);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
2012-05-30 17:07:19 +00:00
|
|
|
if (!instance.IsValidNativeIndex(index)) {
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError(
|
2012-05-30 17:07:19 +00:00
|
|
|
"%s: invalid index %d passed in to access native instance field",
|
|
|
|
CURRENT_FUNC, index);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
2012-11-12 23:21:04 +00:00
|
|
|
*value = instance.GetNativeField(isolate, index);
|
2012-04-04 20:31:49 +00:00
|
|
|
return Api::Success(isolate);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-10-26 20:38:41 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_SetNativeInstanceField(Dart_Handle obj,
|
2011-10-05 05:20:07 +00:00
|
|
|
int index,
|
|
|
|
intptr_t value) {
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
2012-05-30 17:07:19 +00:00
|
|
|
const Instance& instance = Api::UnwrapInstanceHandle(isolate, obj);
|
|
|
|
if (instance.IsNull()) {
|
2012-05-21 21:41:49 +00:00
|
|
|
RETURN_TYPE_ERROR(isolate, obj, Instance);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
2012-05-30 17:07:19 +00:00
|
|
|
if (!instance.IsValidNativeIndex(index)) {
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError(
|
2012-05-30 17:07:19 +00:00
|
|
|
"%s: invalid index %d passed in to set native instance field",
|
|
|
|
CURRENT_FUNC, index);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
2012-05-30 17:07:19 +00:00
|
|
|
instance.SetNativeField(index, value);
|
2012-04-04 20:31:49 +00:00
|
|
|
return Api::Success(isolate);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
// --- Exceptions ----
|
2011-10-05 05:20:07 +00:00
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_ThrowException(Dart_Handle exception) {
|
2011-11-12 05:55:22 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
2012-10-16 22:05:40 +00:00
|
|
|
CHECK_ISOLATE(isolate);
|
|
|
|
{
|
|
|
|
const Instance& excp = Api::UnwrapInstanceHandle(isolate, exception);
|
|
|
|
if (excp.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, exception, Instance);
|
|
|
|
}
|
2012-08-22 13:42:06 +00:00
|
|
|
}
|
2011-11-22 19:42:38 +00:00
|
|
|
if (isolate->top_exit_frame_info() == 0) {
|
|
|
|
// There are no dart frames on the stack so it would be illegal to
|
|
|
|
// throw an exception here.
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("No Dart frames on stack, cannot throw exception");
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
2011-11-22 19:42:38 +00:00
|
|
|
// Unwind all the API scopes till the exit frame before throwing an
|
|
|
|
// exception.
|
|
|
|
ApiState* state = isolate->api_state();
|
|
|
|
ASSERT(state != NULL);
|
2012-10-16 22:05:40 +00:00
|
|
|
const Instance* saved_exception;
|
|
|
|
{
|
|
|
|
NoGCScope no_gc;
|
|
|
|
RawInstance* raw_exception =
|
2012-10-18 22:33:45 +00:00
|
|
|
Api::UnwrapInstanceHandle(isolate, exception).raw();
|
2012-10-16 22:05:40 +00:00
|
|
|
state->UnwindScopes(isolate->top_exit_frame_info());
|
|
|
|
saved_exception = &Instance::Handle(raw_exception);
|
|
|
|
}
|
|
|
|
Exceptions::Throw(*saved_exception);
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("Exception was not thrown, internal error");
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_ReThrowException(Dart_Handle exception,
|
|
|
|
Dart_Handle stacktrace) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
2011-12-01 19:17:10 +00:00
|
|
|
CHECK_ISOLATE(isolate);
|
2012-10-16 22:05:40 +00:00
|
|
|
{
|
|
|
|
const Instance& excp = Api::UnwrapInstanceHandle(isolate, exception);
|
|
|
|
if (excp.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, exception, Instance);
|
|
|
|
}
|
|
|
|
const Instance& stk = Api::UnwrapInstanceHandle(isolate, stacktrace);
|
|
|
|
if (stk.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, stacktrace, Instance);
|
|
|
|
}
|
2012-08-22 13:42:06 +00:00
|
|
|
}
|
2011-11-22 19:42:38 +00:00
|
|
|
if (isolate->top_exit_frame_info() == 0) {
|
|
|
|
// There are no dart frames on the stack so it would be illegal to
|
|
|
|
// throw an exception here.
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("No Dart frames on stack, cannot throw exception");
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
|
|
|
// Unwind all the API scopes till the exit frame before throwing an
|
|
|
|
// exception.
|
|
|
|
ApiState* state = isolate->api_state();
|
|
|
|
ASSERT(state != NULL);
|
2012-10-16 22:05:40 +00:00
|
|
|
const Instance* saved_exception;
|
|
|
|
const Instance* saved_stacktrace;
|
|
|
|
{
|
|
|
|
NoGCScope no_gc;
|
|
|
|
RawInstance* raw_exception =
|
2012-10-18 22:33:45 +00:00
|
|
|
Api::UnwrapInstanceHandle(isolate, exception).raw();
|
2012-10-16 22:05:40 +00:00
|
|
|
RawInstance* raw_stacktrace =
|
2012-10-18 22:33:45 +00:00
|
|
|
Api::UnwrapInstanceHandle(isolate, stacktrace).raw();
|
2012-10-16 22:05:40 +00:00
|
|
|
state->UnwindScopes(isolate->top_exit_frame_info());
|
|
|
|
saved_exception = &Instance::Handle(raw_exception);
|
|
|
|
saved_stacktrace = &Instance::Handle(raw_stacktrace);
|
|
|
|
}
|
|
|
|
Exceptions::ReThrow(*saved_exception, *saved_stacktrace);
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("Exception was not re thrown, internal error");
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
// --- Native functions ---
|
2011-10-05 05:20:07 +00:00
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_GetNativeArgument(Dart_NativeArguments args,
|
|
|
|
int index) {
|
|
|
|
NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
|
2012-11-15 01:14:01 +00:00
|
|
|
if ((index < 0) || (index >= arguments->NativeArgCount())) {
|
2012-04-04 19:47:22 +00:00
|
|
|
return Api::NewError(
|
|
|
|
"%s: argument 'index' out of range. Expected 0..%d but saw %d.",
|
2012-11-15 01:14:01 +00:00
|
|
|
CURRENT_FUNC, arguments->NativeArgCount() - 1, index);
|
2012-04-04 19:47:22 +00:00
|
|
|
}
|
2012-11-15 01:14:01 +00:00
|
|
|
return Api::NewHandle(arguments->isolate(), arguments->NativeArgAt(index));
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
DART_EXPORT int Dart_GetNativeArgumentCount(Dart_NativeArguments args) {
|
|
|
|
NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
|
2012-11-15 01:14:01 +00:00
|
|
|
return arguments->NativeArgCount();
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-08-31 20:12:21 +00:00
|
|
|
// This function has friend access to SetReturnUnsafe.
|
|
|
|
void SetReturnValueHelper(Dart_NativeArguments args, Dart_Handle retval) {
|
2012-08-31 19:59:37 +00:00
|
|
|
NoGCScope no_gc_scope;
|
2011-11-22 19:42:38 +00:00
|
|
|
NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
|
2012-08-31 19:59:37 +00:00
|
|
|
arguments->SetReturnUnsafe(Api::UnwrapHandle(retval));
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-08-31 20:12:21 +00:00
|
|
|
DART_EXPORT void Dart_SetReturnValue(Dart_NativeArguments args,
|
|
|
|
Dart_Handle retval) {
|
|
|
|
SetReturnValueHelper(args, retval);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
// --- Scripts and Libraries ---
|
|
|
|
|
|
|
|
|
2012-05-10 19:17:37 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_SetLibraryTagHandler(
|
|
|
|
Dart_LibraryTagHandler handler) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
CHECK_ISOLATE(isolate);
|
|
|
|
isolate->set_library_tag_handler(handler);
|
|
|
|
return Api::Success(isolate);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
// NOTE: Need to pass 'result' as a parameter here in order to avoid
|
|
|
|
// warning: variable 'result' might be clobbered by 'longjmp' or 'vfork'
|
|
|
|
// which shows up because of the use of setjmp.
|
|
|
|
static void CompileSource(Isolate* isolate,
|
|
|
|
const Library& lib,
|
|
|
|
const String& url,
|
|
|
|
const String& source,
|
|
|
|
RawScript::Kind kind,
|
|
|
|
Dart_Handle* result) {
|
2012-07-20 22:24:49 +00:00
|
|
|
bool update_lib_status = (kind == RawScript::kScriptTag ||
|
|
|
|
kind == RawScript::kLibraryTag);
|
2011-11-22 19:42:38 +00:00
|
|
|
if (update_lib_status) {
|
|
|
|
lib.SetLoadInProgress();
|
|
|
|
}
|
2012-04-04 20:31:49 +00:00
|
|
|
const Script& script =
|
|
|
|
Script::Handle(isolate, Script::New(url, source, kind));
|
2011-11-22 19:42:38 +00:00
|
|
|
ASSERT(isolate != NULL);
|
2012-04-04 20:31:49 +00:00
|
|
|
const Error& error = Error::Handle(isolate, Compiler::Compile(lib, script));
|
2012-02-02 19:05:06 +00:00
|
|
|
if (error.IsNull()) {
|
2012-04-06 17:05:50 +00:00
|
|
|
*result = Api::NewHandle(isolate, lib.raw());
|
2011-11-22 19:42:38 +00:00
|
|
|
if (update_lib_status) {
|
|
|
|
lib.SetLoaded();
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
} else {
|
2012-04-06 17:05:50 +00:00
|
|
|
*result = Api::NewHandle(isolate, error.raw());
|
2011-11-22 19:42:38 +00:00
|
|
|
if (update_lib_status) {
|
|
|
|
lib.SetLoadError();
|
|
|
|
}
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_LoadScript(Dart_Handle url,
|
2012-05-23 18:32:51 +00:00
|
|
|
Dart_Handle source) {
|
2012-01-17 18:29:54 +00:00
|
|
|
TIMERSCOPE(time_script_loading);
|
2011-11-22 19:42:38 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
2012-04-04 20:31:49 +00:00
|
|
|
const String& url_str = Api::UnwrapStringHandle(isolate, url);
|
2011-11-22 19:42:38 +00:00
|
|
|
if (url_str.IsNull()) {
|
2012-04-04 20:31:49 +00:00
|
|
|
RETURN_TYPE_ERROR(isolate, url, String);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
2012-04-04 20:31:49 +00:00
|
|
|
const String& source_str = Api::UnwrapStringHandle(isolate, source);
|
2011-11-22 19:42:38 +00:00
|
|
|
if (source_str.IsNull()) {
|
2012-04-04 20:31:49 +00:00
|
|
|
RETURN_TYPE_ERROR(isolate, source, String);
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
2012-04-04 20:31:49 +00:00
|
|
|
Library& library =
|
|
|
|
Library::Handle(isolate, isolate->object_store()->root_library());
|
2011-11-22 19:42:38 +00:00
|
|
|
if (!library.IsNull()) {
|
2012-04-04 20:31:49 +00:00
|
|
|
const String& library_url = String::Handle(isolate, library.url());
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("%s: A script has already been loaded from '%s'.",
|
|
|
|
CURRENT_FUNC, library_url.ToCString());
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
|
|
|
library = Library::New(url_str);
|
2012-05-31 20:17:34 +00:00
|
|
|
library.set_debuggable(true);
|
2011-11-22 19:42:38 +00:00
|
|
|
library.Register();
|
|
|
|
isolate->object_store()->set_root_library(library);
|
|
|
|
Dart_Handle result;
|
|
|
|
CompileSource(isolate,
|
|
|
|
library,
|
|
|
|
url_str,
|
|
|
|
source_str,
|
2012-07-20 22:24:49 +00:00
|
|
|
RawScript::kScriptTag,
|
2011-11-22 19:42:38 +00:00
|
|
|
&result);
|
|
|
|
return result;
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-12-06 00:34:49 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_LoadScriptFromSnapshot(const uint8_t* buffer) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
2011-12-20 02:04:24 +00:00
|
|
|
TIMERSCOPE(time_script_loading);
|
2011-12-06 00:34:49 +00:00
|
|
|
if (buffer == NULL) {
|
2012-07-09 23:57:08 +00:00
|
|
|
RETURN_NULL_ERROR(buffer);
|
2011-12-06 00:34:49 +00:00
|
|
|
}
|
|
|
|
const Snapshot* snapshot = Snapshot::SetupFromBuffer(buffer);
|
|
|
|
if (!snapshot->IsScriptSnapshot()) {
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("%s expects parameter 'buffer' to be a script type"
|
2012-08-27 20:25:44 +00:00
|
|
|
" snapshot.", CURRENT_FUNC);
|
2011-12-06 00:34:49 +00:00
|
|
|
}
|
2012-04-04 20:31:49 +00:00
|
|
|
Library& library =
|
|
|
|
Library::Handle(isolate, isolate->object_store()->root_library());
|
2011-12-06 00:34:49 +00:00
|
|
|
if (!library.IsNull()) {
|
2012-04-04 20:31:49 +00:00
|
|
|
const String& library_url = String::Handle(isolate, library.url());
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("%s: A script has already been loaded from '%s'.",
|
|
|
|
CURRENT_FUNC, library_url.ToCString());
|
2011-12-06 00:34:49 +00:00
|
|
|
}
|
2012-08-27 20:25:44 +00:00
|
|
|
SnapshotReader reader(snapshot->content(),
|
|
|
|
snapshot->length(),
|
|
|
|
snapshot->kind(),
|
|
|
|
isolate);
|
2012-04-04 20:31:49 +00:00
|
|
|
const Object& tmp = Object::Handle(isolate, reader.ReadObject());
|
2011-12-06 00:34:49 +00:00
|
|
|
if (!tmp.IsLibrary()) {
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("%s: Unable to deserialize snapshot correctly.",
|
|
|
|
CURRENT_FUNC);
|
2011-12-06 00:34:49 +00:00
|
|
|
}
|
|
|
|
library ^= tmp.raw();
|
2012-05-31 20:17:34 +00:00
|
|
|
library.set_debuggable(true);
|
2011-12-06 00:34:49 +00:00
|
|
|
isolate->object_store()->set_root_library(library);
|
2012-04-06 17:05:50 +00:00
|
|
|
return Api::NewHandle(isolate, library.raw());
|
2011-12-06 00:34:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-05-23 18:32:51 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_RootLibrary() {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
Library& library =
|
|
|
|
Library::Handle(isolate, isolate->object_store()->root_library());
|
|
|
|
return Api::NewHandle(isolate, library.raw());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
static void CompileAll(Isolate* isolate, Dart_Handle* result) {
|
2012-01-05 22:33:37 +00:00
|
|
|
ASSERT(isolate != NULL);
|
2012-04-04 20:31:49 +00:00
|
|
|
const Error& error = Error::Handle(isolate, Library::CompileAll());
|
2012-02-02 19:05:06 +00:00
|
|
|
if (error.IsNull()) {
|
2012-04-04 20:31:49 +00:00
|
|
|
*result = Api::Success(isolate);
|
2012-01-05 22:33:37 +00:00
|
|
|
} else {
|
2012-04-06 17:05:50 +00:00
|
|
|
*result = Api::NewHandle(isolate, error.raw());
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_CompileAll() {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
Dart_Handle result;
|
|
|
|
const char* msg = CheckIsolateState(isolate);
|
|
|
|
if (msg != NULL) {
|
2012-09-06 00:58:25 +00:00
|
|
|
return Api::NewError("%s", msg);
|
2011-11-21 19:09:51 +00:00
|
|
|
}
|
2011-11-22 19:42:38 +00:00
|
|
|
CompileAll(isolate, &result);
|
|
|
|
return result;
|
|
|
|
}
|
2011-11-21 19:09:51 +00:00
|
|
|
|
2011-10-05 05:20:07 +00:00
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
DART_EXPORT bool Dart_IsLibrary(Dart_Handle object) {
|
2012-08-08 19:46:23 +00:00
|
|
|
return Api::ClassId(object) == kLibraryCid;
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-05-23 21:54:00 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_GetClass(Dart_Handle library,
|
|
|
|
Dart_Handle class_name) {
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
2012-05-23 21:54:00 +00:00
|
|
|
const Library& lib = Api::UnwrapLibraryHandle(isolate, library);
|
2011-11-22 19:42:38 +00:00
|
|
|
if (lib.IsNull()) {
|
2012-05-23 21:54:00 +00:00
|
|
|
RETURN_TYPE_ERROR(isolate, library, Library);
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
2012-05-23 21:54:00 +00:00
|
|
|
const String& cls_name = Api::UnwrapStringHandle(isolate, class_name);
|
|
|
|
if (cls_name.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, class_name, String);
|
|
|
|
}
|
|
|
|
const Class& cls =
|
|
|
|
Class::Handle(isolate, lib.LookupClassAllowPrivate(cls_name));
|
2011-11-22 19:42:38 +00:00
|
|
|
if (cls.IsNull()) {
|
2012-05-23 21:54:00 +00:00
|
|
|
// TODO(turnidge): Return null or error in this case?
|
2012-04-04 20:31:49 +00:00
|
|
|
const String& lib_name = String::Handle(isolate, lib.name());
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("Class '%s' not found in library '%s'.",
|
|
|
|
cls_name.ToCString(), lib_name.ToCString());
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
2012-04-06 17:05:50 +00:00
|
|
|
return Api::NewHandle(isolate, cls.raw());
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-05-30 17:07:19 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_LibraryName(Dart_Handle library) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
const Library& lib = Api::UnwrapLibraryHandle(isolate, library);
|
|
|
|
if (lib.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, library, Library);
|
|
|
|
}
|
|
|
|
const String& name = String::Handle(isolate, lib.name());
|
|
|
|
ASSERT(!name.IsNull());
|
|
|
|
return Api::NewHandle(isolate, name.raw());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_LibraryUrl(Dart_Handle library) {
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
const Library& lib = Api::UnwrapLibraryHandle(isolate, library);
|
2011-11-22 19:42:38 +00:00
|
|
|
if (lib.IsNull()) {
|
2012-04-04 20:31:49 +00:00
|
|
|
RETURN_TYPE_ERROR(isolate, library, Library);
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
2012-04-04 20:31:49 +00:00
|
|
|
const String& url = String::Handle(isolate, lib.url());
|
2011-11-22 19:42:38 +00:00
|
|
|
ASSERT(!url.IsNull());
|
2012-04-06 17:05:50 +00:00
|
|
|
return Api::NewHandle(isolate, url.raw());
|
2011-10-26 20:38:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-06-12 21:07:49 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_LibraryGetClassNames(Dart_Handle library) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
const Library& lib = Api::UnwrapLibraryHandle(isolate, library);
|
|
|
|
if (lib.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, library, Library);
|
|
|
|
}
|
|
|
|
|
|
|
|
const GrowableObjectArray& names =
|
|
|
|
GrowableObjectArray::Handle(isolate, GrowableObjectArray::New());
|
|
|
|
ClassDictionaryIterator it(lib);
|
|
|
|
Class& cls = Class::Handle();
|
|
|
|
String& name = String::Handle();
|
|
|
|
while (it.HasNext()) {
|
|
|
|
cls = it.GetNextClass();
|
2012-09-13 17:47:25 +00:00
|
|
|
if (cls.IsSignatureClass()) {
|
|
|
|
if (!cls.IsCanonicalSignatureClass()) {
|
|
|
|
// This is a typedef. Add it to the list of class names.
|
|
|
|
name = cls.UserVisibleName();
|
|
|
|
names.Add(name);
|
|
|
|
} else {
|
|
|
|
// Skip canonical signature classes. These are not named.
|
|
|
|
}
|
|
|
|
} else {
|
2012-08-08 17:22:26 +00:00
|
|
|
name = cls.UserVisibleName();
|
2012-07-09 23:57:08 +00:00
|
|
|
names.Add(name);
|
|
|
|
}
|
2012-06-12 21:07:49 +00:00
|
|
|
}
|
|
|
|
return Api::NewHandle(isolate, Array::MakeArray(names));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_LookupLibrary(Dart_Handle url) {
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
const String& url_str = Api::UnwrapStringHandle(isolate, url);
|
2011-11-22 19:42:38 +00:00
|
|
|
if (url_str.IsNull()) {
|
2012-04-04 20:31:49 +00:00
|
|
|
RETURN_TYPE_ERROR(isolate, url, String);
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
2012-04-04 20:31:49 +00:00
|
|
|
const Library& library =
|
|
|
|
Library::Handle(isolate, Library::LookupLibrary(url_str));
|
2011-11-22 19:42:38 +00:00
|
|
|
if (library.IsNull()) {
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("%s: library '%s' not found.",
|
|
|
|
CURRENT_FUNC, url_str.ToCString());
|
2011-11-22 19:42:38 +00:00
|
|
|
} else {
|
2012-04-06 17:05:50 +00:00
|
|
|
return Api::NewHandle(isolate, library.raw());
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
|
|
|
}
|
2011-11-08 00:12:59 +00:00
|
|
|
|
|
|
|
|
2012-02-13 22:50:19 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_LoadLibrary(Dart_Handle url,
|
2012-05-23 18:32:51 +00:00
|
|
|
Dart_Handle source) {
|
2012-01-17 18:29:54 +00:00
|
|
|
TIMERSCOPE(time_script_loading);
|
2011-11-22 19:42:38 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
2012-04-04 20:31:49 +00:00
|
|
|
const String& url_str = Api::UnwrapStringHandle(isolate, url);
|
2011-11-22 19:42:38 +00:00
|
|
|
if (url_str.IsNull()) {
|
2012-04-04 20:31:49 +00:00
|
|
|
RETURN_TYPE_ERROR(isolate, url, String);
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
2012-04-04 20:31:49 +00:00
|
|
|
const String& source_str = Api::UnwrapStringHandle(isolate, source);
|
2011-11-22 19:42:38 +00:00
|
|
|
if (source_str.IsNull()) {
|
2012-04-04 20:31:49 +00:00
|
|
|
RETURN_TYPE_ERROR(isolate, source, String);
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
2012-04-04 20:31:49 +00:00
|
|
|
Library& library = Library::Handle(isolate, Library::LookupLibrary(url_str));
|
2011-11-22 19:42:38 +00:00
|
|
|
if (library.IsNull()) {
|
|
|
|
library = Library::New(url_str);
|
|
|
|
library.Register();
|
|
|
|
} else if (!library.LoadNotStarted()) {
|
|
|
|
// The source for this library has either been loaded or is in the
|
|
|
|
// process of loading. Return an error.
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("%s: library '%s' has already been loaded.",
|
|
|
|
CURRENT_FUNC, url_str.ToCString());
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
|
|
|
Dart_Handle result;
|
|
|
|
CompileSource(isolate,
|
|
|
|
library,
|
|
|
|
url_str,
|
|
|
|
source_str,
|
2012-07-20 22:24:49 +00:00
|
|
|
RawScript::kLibraryTag,
|
2011-11-22 19:42:38 +00:00
|
|
|
&result);
|
2012-03-08 23:29:45 +00:00
|
|
|
// Propagate the error out right now.
|
2012-03-08 23:38:29 +00:00
|
|
|
if (::Dart_IsError(result)) {
|
2012-03-08 23:29:45 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If this is the dart:builtin library, register it with the VM.
|
|
|
|
if (url_str.Equals("dart:builtin")) {
|
|
|
|
isolate->object_store()->set_builtin_library(library);
|
|
|
|
const char* msg = CheckIsolateState(isolate);
|
|
|
|
if (msg != NULL) {
|
2012-09-06 00:58:25 +00:00
|
|
|
return Api::NewError("%s", msg);
|
2012-03-08 23:29:45 +00:00
|
|
|
}
|
|
|
|
}
|
2011-11-22 19:42:38 +00:00
|
|
|
return result;
|
2011-10-26 20:38:41 +00:00
|
|
|
}
|
|
|
|
|
2011-11-08 00:12:59 +00:00
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_LibraryImportLibrary(Dart_Handle library,
|
2012-08-29 08:35:43 +00:00
|
|
|
Dart_Handle import,
|
|
|
|
Dart_Handle prefix) {
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
const Library& library_vm = Api::UnwrapLibraryHandle(isolate, library);
|
2011-11-22 19:42:38 +00:00
|
|
|
if (library_vm.IsNull()) {
|
2012-04-04 20:31:49 +00:00
|
|
|
RETURN_TYPE_ERROR(isolate, library, Library);
|
2011-11-11 19:31:04 +00:00
|
|
|
}
|
2012-04-04 20:31:49 +00:00
|
|
|
const Library& import_vm = Api::UnwrapLibraryHandle(isolate, import);
|
2011-11-22 19:42:38 +00:00
|
|
|
if (import_vm.IsNull()) {
|
2012-04-04 20:31:49 +00:00
|
|
|
RETURN_TYPE_ERROR(isolate, import, Library);
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
2012-08-29 09:05:47 +00:00
|
|
|
const Object& prefix_object =
|
|
|
|
Object::Handle(isolate, Api::UnwrapHandle(prefix));
|
|
|
|
const String& prefix_vm = prefix_object.IsNull()
|
2012-08-29 08:35:43 +00:00
|
|
|
? String::Handle(isolate, Symbols::New(""))
|
2012-08-29 09:05:47 +00:00
|
|
|
: String::Cast(prefix_object);
|
2012-08-29 08:35:43 +00:00
|
|
|
if (prefix_vm.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, prefix, String);
|
|
|
|
}
|
|
|
|
const String& prefix_symbol =
|
|
|
|
String::Handle(isolate, Symbols::New(prefix_vm));
|
2012-09-24 20:46:56 +00:00
|
|
|
const Namespace& import_ns = Namespace::Handle(
|
|
|
|
Namespace::New(import_vm, Array::Handle(), Array::Handle()));
|
2012-08-29 08:35:43 +00:00
|
|
|
if (prefix_vm.Length() == 0) {
|
2012-09-24 20:46:56 +00:00
|
|
|
library_vm.AddImport(import_ns);
|
2012-08-29 08:35:43 +00:00
|
|
|
} else {
|
|
|
|
LibraryPrefix& library_prefix = LibraryPrefix::Handle();
|
|
|
|
library_prefix = library_vm.LookupLocalLibraryPrefix(prefix_symbol);
|
|
|
|
if (!library_prefix.IsNull()) {
|
2012-09-24 20:46:56 +00:00
|
|
|
library_prefix.AddImport(import_ns);
|
2012-08-29 08:35:43 +00:00
|
|
|
} else {
|
2012-09-24 20:46:56 +00:00
|
|
|
library_prefix = LibraryPrefix::New(prefix_symbol, import_ns);
|
2012-08-29 08:35:43 +00:00
|
|
|
library_vm.AddObject(library_prefix, prefix_symbol);
|
|
|
|
}
|
|
|
|
}
|
2012-04-04 20:31:49 +00:00
|
|
|
return Api::Success(isolate);
|
2011-11-11 19:31:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_LoadSource(Dart_Handle library,
|
|
|
|
Dart_Handle url,
|
|
|
|
Dart_Handle source) {
|
2012-01-17 18:29:54 +00:00
|
|
|
TIMERSCOPE(time_script_loading);
|
2011-11-05 00:09:36 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
2011-11-22 19:42:38 +00:00
|
|
|
DARTSCOPE(isolate);
|
2012-04-04 20:31:49 +00:00
|
|
|
const Library& lib = Api::UnwrapLibraryHandle(isolate, library);
|
2011-11-22 19:42:38 +00:00
|
|
|
if (lib.IsNull()) {
|
2012-04-04 20:31:49 +00:00
|
|
|
RETURN_TYPE_ERROR(isolate, library, Library);
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
2012-04-04 20:31:49 +00:00
|
|
|
const String& url_str = Api::UnwrapStringHandle(isolate, url);
|
2011-11-22 19:42:38 +00:00
|
|
|
if (url_str.IsNull()) {
|
2012-04-04 20:31:49 +00:00
|
|
|
RETURN_TYPE_ERROR(isolate, url, String);
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
2012-04-04 20:31:49 +00:00
|
|
|
const String& source_str = Api::UnwrapStringHandle(isolate, source);
|
2011-11-22 19:42:38 +00:00
|
|
|
if (source_str.IsNull()) {
|
2012-04-04 20:31:49 +00:00
|
|
|
RETURN_TYPE_ERROR(isolate, source, String);
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
|
|
|
Dart_Handle result;
|
2012-07-20 22:24:49 +00:00
|
|
|
CompileSource(isolate, lib, url_str, source_str,
|
|
|
|
RawScript::kSourceTag, &result);
|
2011-11-22 19:42:38 +00:00
|
|
|
return result;
|
2011-11-05 00:09:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-10-26 08:00:05 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_LoadPatch(Dart_Handle library,
|
|
|
|
Dart_Handle url,
|
|
|
|
Dart_Handle patch_source) {
|
|
|
|
TIMERSCOPE(time_script_loading);
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
const Library& lib = Api::UnwrapLibraryHandle(isolate, library);
|
|
|
|
if (lib.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, library, Library);
|
|
|
|
}
|
|
|
|
const String& url_str = Api::UnwrapStringHandle(isolate, url);
|
|
|
|
if (url_str.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, url, String);
|
|
|
|
}
|
|
|
|
const String& source_str = Api::UnwrapStringHandle(isolate, patch_source);
|
|
|
|
if (source_str.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(isolate, patch_source, String);
|
|
|
|
}
|
|
|
|
Dart_Handle result;
|
|
|
|
CompileSource(isolate, lib, url_str, source_str,
|
|
|
|
RawScript::kPatchTag, &result);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_SetNativeResolver(
|
|
|
|
Dart_Handle library,
|
|
|
|
Dart_NativeEntryResolver resolver) {
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
const Library& lib = Api::UnwrapLibraryHandle(isolate, library);
|
2011-11-22 19:42:38 +00:00
|
|
|
if (lib.IsNull()) {
|
2012-04-04 20:31:49 +00:00
|
|
|
RETURN_TYPE_ERROR(isolate, library, Library);
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
|
|
|
lib.set_native_entry_resolver(resolver);
|
2012-04-04 20:31:49 +00:00
|
|
|
return Api::Success(isolate);
|
2011-11-05 00:09:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
// --- Profiling support ----
|
2011-11-05 00:09:36 +00:00
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
DART_EXPORT void Dart_InitPprofSupport() {
|
|
|
|
DebugInfo* pprof_symbol_generator = DebugInfo::NewGenerator();
|
|
|
|
ASSERT(pprof_symbol_generator != NULL);
|
|
|
|
Dart::set_pprof_symbol_generator(pprof_symbol_generator);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
DART_EXPORT void Dart_GetPprofSymbolInfo(void** buffer, int* buffer_size) {
|
2012-04-04 20:31:49 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
2011-11-22 19:42:38 +00:00
|
|
|
DebugInfo* pprof_symbol_generator = Dart::pprof_symbol_generator();
|
|
|
|
if (pprof_symbol_generator != NULL) {
|
2012-01-13 01:39:23 +00:00
|
|
|
DebugInfo::ByteBuffer* debug_region = new DebugInfo::ByteBuffer();
|
2011-11-22 19:42:38 +00:00
|
|
|
ASSERT(debug_region != NULL);
|
|
|
|
pprof_symbol_generator->WriteToMemory(debug_region);
|
|
|
|
*buffer_size = debug_region->size();
|
|
|
|
if (*buffer_size != 0) {
|
2012-10-16 22:05:40 +00:00
|
|
|
Zone* zone = Api::TopScope(isolate)->zone();
|
2012-08-03 21:51:44 +00:00
|
|
|
*buffer = reinterpret_cast<void*>(zone->AllocUnsafe(*buffer_size));
|
2011-11-22 19:42:38 +00:00
|
|
|
memmove(*buffer, debug_region->data(), *buffer_size);
|
|
|
|
} else {
|
|
|
|
*buffer = NULL;
|
|
|
|
}
|
|
|
|
delete debug_region;
|
|
|
|
} else {
|
|
|
|
*buffer = NULL;
|
|
|
|
*buffer_size = 0;
|
|
|
|
}
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
2012-06-06 11:09:02 +00:00
|
|
|
|
2012-12-06 21:56:31 +00:00
|
|
|
DART_EXPORT void Dart_InitPerfEventsSupport(void* perf_events_file) {
|
|
|
|
Dart::set_perf_events_file(perf_events_file);
|
2012-07-26 00:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-18 21:15:46 +00:00
|
|
|
// --- Peer support ---
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_GetPeer(Dart_Handle object, void** peer) {
|
|
|
|
if (peer == NULL) {
|
|
|
|
RETURN_NULL_ERROR(peer);
|
|
|
|
}
|
|
|
|
Isolate* isolate = Isolate::Current();
|
2012-10-10 23:36:13 +00:00
|
|
|
DARTSCOPE(isolate);
|
2012-09-18 21:15:46 +00:00
|
|
|
const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(object));
|
|
|
|
if (obj.IsNull() || obj.IsNumber() || obj.IsBool()) {
|
|
|
|
const char* msg =
|
|
|
|
"%s: argument 'object' cannot be a subtype of Null, num, or bool";
|
|
|
|
return Api::NewError(msg, CURRENT_FUNC);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
NoGCScope no_gc;
|
|
|
|
RawObject* raw_obj = obj.raw();
|
|
|
|
*peer = isolate->heap()->GetPeer(raw_obj);
|
|
|
|
}
|
|
|
|
return Api::Success(isolate);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_SetPeer(Dart_Handle object, void* peer) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
2012-10-10 23:36:13 +00:00
|
|
|
DARTSCOPE(isolate);
|
2012-09-18 21:15:46 +00:00
|
|
|
const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(object));
|
|
|
|
if (obj.IsNull() || obj.IsNumber() || obj.IsBool()) {
|
|
|
|
const char* msg =
|
|
|
|
"%s: argument 'object' cannot be a subtype of Null, num, or bool";
|
|
|
|
return Api::NewError(msg, CURRENT_FUNC);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
NoGCScope no_gc;
|
|
|
|
RawObject* raw_obj = obj.raw();
|
|
|
|
isolate->heap()->SetPeer(raw_obj, peer);
|
|
|
|
}
|
|
|
|
return Api::Success(isolate);
|
|
|
|
}
|
|
|
|
|
2011-10-05 05:20:07 +00:00
|
|
|
} // namespace dart
|