2011-10-05 05:20:07 +00:00
|
|
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
#include "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"
|
|
|
|
#include "vm/dart_api_state.h"
|
|
|
|
#include "vm/dart_entry.h"
|
|
|
|
#include "vm/debuginfo.h"
|
|
|
|
#include "vm/exceptions.h"
|
|
|
|
#include "vm/growable_array.h"
|
2012-02-01 23:39:28 +00:00
|
|
|
#include "vm/longjump.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/snapshot.h"
|
|
|
|
#include "vm/stack_frame.h"
|
|
|
|
#include "vm/timer.h"
|
|
|
|
#include "vm/verifier.h"
|
|
|
|
|
|
|
|
namespace dart {
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-11-21 19:09:51 +00:00
|
|
|
#define RETURN_TYPE_ERROR(dart_handle, Type) \
|
2011-11-10 19:10:53 +00:00
|
|
|
do { \
|
|
|
|
const Object& tmp = Object::Handle(Api::UnwrapHandle((dart_handle))); \
|
2011-11-21 19:09:51 +00:00
|
|
|
if (tmp.IsNull()) { \
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("%s expects argument '%s' to be non-null.", \
|
|
|
|
CURRENT_FUNC, #dart_handle); \
|
|
|
|
} else if (tmp.IsError()) { \
|
2011-11-10 19:10:53 +00:00
|
|
|
return dart_handle; \
|
|
|
|
} else { \
|
2012-01-10 21:42:21 +00:00
|
|
|
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)
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
// Return error if isolate is in an inconsistent state.
|
|
|
|
// Return NULL when no error condition exists.
|
2011-12-07 22:13:49 +00:00
|
|
|
const char* CheckIsolateState(Isolate* isolate, bool generating_snapshot) {
|
2011-12-23 00:46:00 +00:00
|
|
|
bool success = true;
|
|
|
|
if (!ClassFinalizer::AllClassesFinalized()) {
|
|
|
|
success = (generating_snapshot) ?
|
|
|
|
ClassFinalizer::FinalizePendingClassesForSnapshotCreation() :
|
|
|
|
ClassFinalizer::FinalizePendingClasses();
|
|
|
|
}
|
2011-12-06 23:01:46 +00:00
|
|
|
if (success && !generating_snapshot) {
|
|
|
|
success = isolate->object_store()->PreallocateObjects();
|
|
|
|
}
|
|
|
|
if (success) {
|
|
|
|
return NULL;
|
|
|
|
} else {
|
2011-11-22 19:42:38 +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.
|
2012-01-17 19:54:02 +00:00
|
|
|
const Error& err =
|
|
|
|
Error::Handle(isolate->object_store()->sticky_error());
|
|
|
|
const char* errmsg = err.ToErrorCString();
|
2011-11-22 19:42:38 +00:00
|
|
|
intptr_t errlen = strlen(errmsg) + 1;
|
|
|
|
char* msg = reinterpret_cast<char*>(Api::Allocate(errlen));
|
|
|
|
OS::SNPrint(msg, errlen, "%s", errmsg);
|
|
|
|
return msg;
|
|
|
|
}
|
2011-11-11 19:31:04 +00:00
|
|
|
}
|
|
|
|
|
2011-10-19 18:41:33 +00:00
|
|
|
|
2011-12-07 22:13:49 +00:00
|
|
|
void SetupErrorResult(Dart_Handle* handle) {
|
2012-01-17 19:54:02 +00:00
|
|
|
const Error& error = Error::Handle(
|
2011-11-22 19:42:38 +00:00
|
|
|
Isolate::Current()->object_store()->sticky_error());
|
2012-01-17 19:54:02 +00:00
|
|
|
*handle = Api::NewLocalHandle(error);
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-02-01 23:39:28 +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 InvokeStatic(Isolate* isolate,
|
|
|
|
const Function& function,
|
|
|
|
GrowableArray<const Object*>& args,
|
|
|
|
Dart_Handle* result) {
|
|
|
|
ASSERT(isolate != NULL);
|
|
|
|
LongJump* base = isolate->long_jump_base();
|
|
|
|
LongJump jump;
|
|
|
|
isolate->set_long_jump_base(&jump);
|
|
|
|
if (setjmp(*jump.Set()) == 0) {
|
|
|
|
const Array& kNoArgumentNames = Array::Handle();
|
|
|
|
const Instance& retval = Instance::Handle(
|
|
|
|
DartEntry::InvokeStatic(function, args, kNoArgumentNames));
|
|
|
|
*result = Api::NewLocalHandle(retval);
|
|
|
|
} else {
|
|
|
|
SetupErrorResult(result);
|
|
|
|
}
|
|
|
|
isolate->set_long_jump_base(base);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 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 InvokeDynamic(Isolate* isolate,
|
|
|
|
const Instance& receiver,
|
|
|
|
const Function& function,
|
|
|
|
GrowableArray<const Object*>& args,
|
|
|
|
Dart_Handle* result) {
|
|
|
|
ASSERT(isolate != NULL);
|
|
|
|
LongJump* base = isolate->long_jump_base();
|
|
|
|
LongJump jump;
|
|
|
|
isolate->set_long_jump_base(&jump);
|
|
|
|
if (setjmp(*jump.Set()) == 0) {
|
|
|
|
const Array& kNoArgumentNames = Array::Handle();
|
|
|
|
const Instance& retval = Instance::Handle(
|
|
|
|
DartEntry::InvokeDynamic(receiver, function, args, kNoArgumentNames));
|
|
|
|
*result = Api::NewLocalHandle(retval);
|
|
|
|
} else {
|
|
|
|
SetupErrorResult(result);
|
|
|
|
}
|
|
|
|
isolate->set_long_jump_base(base);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
Dart_Handle Api::NewLocalHandle(const Object& object) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
ASSERT(isolate != NULL);
|
|
|
|
ApiState* state = isolate->api_state();
|
|
|
|
ASSERT(state != NULL);
|
|
|
|
ApiLocalScope* scope = state->top_scope();
|
|
|
|
ASSERT(scope != NULL);
|
|
|
|
LocalHandles* local_handles = scope->local_handles();
|
|
|
|
ASSERT(local_handles != NULL);
|
|
|
|
LocalHandle* ref = local_handles->AllocateHandle();
|
|
|
|
ref->set_raw(object);
|
|
|
|
return reinterpret_cast<Dart_Handle>(ref);
|
|
|
|
}
|
|
|
|
|
|
|
|
RawObject* Api::UnwrapHandle(Dart_Handle object) {
|
|
|
|
#ifdef DEBUG
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
ASSERT(isolate != NULL);
|
|
|
|
ApiState* state = isolate->api_state();
|
|
|
|
ASSERT(state != NULL);
|
2012-01-13 01:23:42 +00:00
|
|
|
ASSERT(state->IsValidWeakPersistentHandle(object) ||
|
|
|
|
state->IsValidPersistentHandle(object) ||
|
2011-11-22 19:42:38 +00:00
|
|
|
state->IsValidLocalHandle(object));
|
2012-01-13 01:23:42 +00:00
|
|
|
ASSERT(WeakPersistentHandle::raw_offset() == 0 &&
|
|
|
|
PersistentHandle::raw_offset() == 0 &&
|
2011-11-22 19:42:38 +00:00
|
|
|
LocalHandle::raw_offset() == 0);
|
|
|
|
#endif
|
|
|
|
return *(reinterpret_cast<RawObject**>(object));
|
|
|
|
}
|
|
|
|
|
|
|
|
#define DEFINE_UNWRAP(Type) \
|
|
|
|
const Type& Api::Unwrap##Type##Handle(Dart_Handle dart_handle) { \
|
|
|
|
const Object& tmp = Object::Handle(Api::UnwrapHandle(dart_handle)); \
|
|
|
|
Type& typed_handle = Type::Handle(); \
|
|
|
|
if (tmp.Is##Type()) { \
|
|
|
|
typed_handle ^= tmp.raw(); \
|
|
|
|
} \
|
|
|
|
return typed_handle; \
|
2011-11-11 19:31:04 +00:00
|
|
|
}
|
2011-11-22 19:42:38 +00:00
|
|
|
CLASS_LIST_NO_OBJECT(DEFINE_UNWRAP)
|
|
|
|
#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-01-13 01:23:42 +00:00
|
|
|
WeakPersistentHandle* Api::UnwrapAsWeakPersistentHandle(const ApiState& state,
|
|
|
|
Dart_Handle object) {
|
|
|
|
ASSERT(state.IsValidWeakPersistentHandle(object));
|
|
|
|
return reinterpret_cast<WeakPersistentHandle*>(object);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-12-01 18:18:06 +00:00
|
|
|
Dart_Isolate Api::CastIsolate(Isolate* isolate) {
|
|
|
|
return reinterpret_cast<Dart_Isolate>(isolate);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
Dart_Handle Api::Success() {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
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, ...) {
|
2011-12-01 19:17:10 +00:00
|
|
|
DARTSCOPE_NOCHECKS(Isolate::Current());
|
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);
|
|
|
|
|
|
|
|
char* buffer = reinterpret_cast<char*>(zone.Allocate(len + 1));
|
|
|
|
va_list args2;
|
|
|
|
va_start(args2, format);
|
|
|
|
OS::VSNPrint(buffer, (len + 1), format, args2);
|
|
|
|
va_end(args2);
|
|
|
|
|
|
|
|
const String& message = String::Handle(String::New(buffer));
|
|
|
|
const Object& obj = Object::Handle(ApiError::New(message));
|
|
|
|
return Api::NewLocalHandle(obj);
|
2011-11-11 19:31:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
Dart_Handle Api::Null() {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
ASSERT(isolate != NULL);
|
|
|
|
ApiState* state = isolate->api_state();
|
|
|
|
ASSERT(state != NULL);
|
|
|
|
PersistentHandle* null_handle = state->Null();
|
|
|
|
return reinterpret_cast<Dart_Handle>(null_handle);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Dart_Handle Api::True() {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
ASSERT(isolate != NULL);
|
|
|
|
ApiState* state = isolate->api_state();
|
|
|
|
ASSERT(state != NULL);
|
|
|
|
PersistentHandle* true_handle = state->True();
|
|
|
|
return reinterpret_cast<Dart_Handle>(true_handle);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Dart_Handle Api::False() {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
ASSERT(isolate != NULL);
|
|
|
|
ApiState* state = isolate->api_state();
|
|
|
|
ASSERT(state != NULL);
|
|
|
|
PersistentHandle* false_handle = state->False();
|
|
|
|
return reinterpret_cast<Dart_Handle>(false_handle);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uword Api::Allocate(intptr_t size) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
ASSERT(isolate != NULL);
|
|
|
|
ApiState* state = isolate->api_state();
|
|
|
|
ASSERT(state != NULL);
|
|
|
|
ApiLocalScope* scope = state->top_scope();
|
|
|
|
ASSERT(scope != NULL);
|
|
|
|
return scope->zone().Allocate(size);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uword Api::Reallocate(uword ptr, intptr_t old_size, intptr_t new_size) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
ASSERT(isolate != NULL);
|
|
|
|
ApiState* state = isolate->api_state();
|
|
|
|
ASSERT(state != NULL);
|
|
|
|
ApiLocalScope* scope = state->top_scope();
|
|
|
|
ASSERT(scope != NULL);
|
|
|
|
return scope->zone().Reallocate(ptr, old_size, new_size);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// --- Handles ---
|
|
|
|
|
|
|
|
|
2011-12-21 17:50:38 +00:00
|
|
|
DART_EXPORT bool Dart_IsError(Dart_Handle handle) {
|
2011-11-22 19:42:38 +00:00
|
|
|
DARTSCOPE(Isolate::Current());
|
|
|
|
const Object& obj = Object::Handle(Api::UnwrapHandle(handle));
|
2012-01-10 21:42:21 +00:00
|
|
|
return obj.IsError();
|
2011-10-31 20:18:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-12-21 17:50:38 +00:00
|
|
|
DART_EXPORT const char* Dart_GetError(Dart_Handle handle) {
|
2011-11-12 05:55:22 +00:00
|
|
|
DARTSCOPE(Isolate::Current());
|
2011-10-26 20:38:41 +00:00
|
|
|
const Object& obj = Object::Handle(Api::UnwrapHandle(handle));
|
2012-01-12 01:01:46 +00:00
|
|
|
if (obj.IsError()) {
|
|
|
|
Error& error = Error::Handle();
|
2012-01-10 21:42:21 +00:00
|
|
|
error ^= obj.raw();
|
2012-01-12 01:01:46 +00:00
|
|
|
const char* str = error.ToErrorCString();
|
|
|
|
intptr_t len = strlen(str) + 1;
|
|
|
|
char* str_copy = reinterpret_cast<char*>(Api::Allocate(len));
|
|
|
|
strncpy(str_copy, str, len);
|
|
|
|
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) {
|
2011-11-12 05:55:22 +00:00
|
|
|
DARTSCOPE(Isolate::Current());
|
2011-11-22 19:42:38 +00:00
|
|
|
const Object& obj = Object::Handle(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) {
|
|
|
|
DARTSCOPE(Isolate::Current());
|
|
|
|
const Object& obj = Object::Handle(Api::UnwrapHandle(handle));
|
2012-01-10 21:42:21 +00:00
|
|
|
if (obj.IsUnhandledException()) {
|
|
|
|
UnhandledException& error = UnhandledException::Handle();
|
|
|
|
error ^= obj.raw();
|
|
|
|
const Object& exception = Object::Handle(error.exception());
|
|
|
|
return Api::NewLocalHandle(exception);
|
|
|
|
} 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) {
|
|
|
|
DARTSCOPE(Isolate::Current());
|
|
|
|
const Object& obj = Object::Handle(Api::UnwrapHandle(handle));
|
2012-01-10 21:42:21 +00:00
|
|
|
if (obj.IsUnhandledException()) {
|
|
|
|
UnhandledException& error = UnhandledException::Handle();
|
|
|
|
error ^= obj.raw();
|
|
|
|
const Object& stacktrace = Object::Handle(error.stacktrace());
|
|
|
|
return Api::NewLocalHandle(stacktrace);
|
|
|
|
} 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-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.
|
|
|
|
DART_EXPORT Dart_Handle Dart_Error(const char* format, ...) {
|
|
|
|
DARTSCOPE(Isolate::Current());
|
|
|
|
|
|
|
|
va_list args;
|
|
|
|
va_start(args, format);
|
|
|
|
intptr_t len = OS::VSNPrint(NULL, 0, format, args);
|
|
|
|
va_end(args);
|
|
|
|
|
|
|
|
char* buffer = reinterpret_cast<char*>(zone.Allocate(len + 1));
|
|
|
|
va_list args2;
|
|
|
|
va_start(args2, format);
|
|
|
|
OS::VSNPrint(buffer, (len + 1), format, args2);
|
|
|
|
va_end(args2);
|
|
|
|
|
|
|
|
const String& message = String::Handle(String::New(buffer));
|
|
|
|
const Object& obj = Object::Handle(ApiError::New(message));
|
|
|
|
return Api::NewLocalHandle(obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT void _Dart_ReportErrorHandle(const char* file,
|
|
|
|
int line,
|
|
|
|
const char* handle,
|
|
|
|
const char* message) {
|
|
|
|
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) {
|
|
|
|
DARTSCOPE(Isolate::Current());
|
|
|
|
const Object& obj = Object::Handle(Api::UnwrapHandle(object));
|
|
|
|
Object& result = Object::Handle();
|
|
|
|
if (obj.IsString()) {
|
|
|
|
result = obj.raw();
|
|
|
|
} else if (obj.IsInstance()) {
|
|
|
|
Instance& receiver = Instance::Handle();
|
|
|
|
receiver ^= obj.raw();
|
|
|
|
result = DartLibraryCalls::ToString(receiver);
|
|
|
|
} else {
|
|
|
|
// This is a VM internal object. Call the C++ method of printing.
|
|
|
|
result = String::New(obj.ToCString());
|
|
|
|
}
|
|
|
|
return Api::NewLocalHandle(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_IsSame(Dart_Handle obj1, Dart_Handle obj2,
|
|
|
|
bool* value) {
|
|
|
|
DARTSCOPE(Isolate::Current());
|
|
|
|
const Object& expected = Object::Handle(Api::UnwrapHandle(obj1));
|
|
|
|
const Object& actual = Object::Handle(Api::UnwrapHandle(obj2));
|
|
|
|
*value = (expected.raw() == actual.raw());
|
|
|
|
return Api::Success();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
const Object& old_ref = Object::Handle(Api::UnwrapHandle(object));
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_NewWeakPersistentHandle(
|
|
|
|
Dart_Handle object,
|
|
|
|
void* peer,
|
|
|
|
Dart_PeerFinalizer 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);
|
|
|
|
const Object& old_ref = Object::Handle(Api::UnwrapHandle(object));
|
|
|
|
WeakPersistentHandle* new_ref =
|
|
|
|
state->weak_persistent_handles().AllocateHandle();
|
|
|
|
new_ref->set_raw(old_ref);
|
2011-12-20 01:44:53 +00:00
|
|
|
new_ref->set_peer(peer);
|
|
|
|
new_ref->set_callback(callback);
|
2011-11-22 19:42:38 +00:00
|
|
|
return reinterpret_cast<Dart_Handle>(new_ref);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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-01-13 01:23:42 +00:00
|
|
|
if (state->IsValidWeakPersistentHandle(object)) {
|
|
|
|
WeakPersistentHandle* weak_ref =
|
|
|
|
Api::UnwrapAsWeakPersistentHandle(*state, object);
|
|
|
|
state->weak_persistent_handles().FreeHandle(weak_ref);
|
|
|
|
} else {
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// --- Initialization and Globals ---
|
|
|
|
|
|
|
|
|
2011-12-16 18:41:20 +00:00
|
|
|
DART_EXPORT bool Dart_Initialize(Dart_IsolateCreateCallback create,
|
|
|
|
Dart_IsolateInterruptCallback interrupt) {
|
|
|
|
return Dart::InitOnce(create, interrupt);
|
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-01-18 21:46:27 +00:00
|
|
|
DART_EXPORT Dart_Isolate Dart_CreateIsolate(const char* name_prefix,
|
|
|
|
const uint8_t* snapshot,
|
2011-12-01 00:30:25 +00:00
|
|
|
void* callback_data,
|
|
|
|
char** error) {
|
2012-01-18 21:46:27 +00:00
|
|
|
Isolate* isolate = Dart::CreateIsolate(name_prefix);
|
2011-12-01 19:17:10 +00:00
|
|
|
assert(isolate != NULL);
|
2012-02-01 23:39:28 +00:00
|
|
|
LongJump* base = isolate->long_jump_base();
|
|
|
|
LongJump jump;
|
|
|
|
isolate->set_long_jump_base(&jump);
|
|
|
|
if (setjmp(*jump.Set()) == 0) {
|
|
|
|
Dart::InitializeIsolate(snapshot, callback_data);
|
2011-11-04 22:08:13 +00:00
|
|
|
START_TIMER(time_total_runtime);
|
2012-02-01 23:39:28 +00:00
|
|
|
isolate->set_long_jump_base(base);
|
2011-11-04 22:08:13 +00:00
|
|
|
return reinterpret_cast<Dart_Isolate>(isolate);
|
|
|
|
} else {
|
2012-02-01 23:39:28 +00:00
|
|
|
{
|
|
|
|
DARTSCOPE_NOCHECKS(isolate);
|
|
|
|
const Error& error_obj =
|
|
|
|
Error::Handle(isolate->object_store()->sticky_error());
|
|
|
|
*error = strdup(error_obj.ToErrorCString());
|
|
|
|
}
|
2011-11-04 22:08:13 +00:00
|
|
|
Dart::ShutdownIsolate();
|
|
|
|
}
|
2012-02-01 23:39:28 +00:00
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
static uint8_t* ApiAllocator(uint8_t* ptr,
|
|
|
|
intptr_t old_size,
|
|
|
|
intptr_t new_size) {
|
|
|
|
uword new_ptr = Api::Reallocate(reinterpret_cast<uword>(ptr),
|
|
|
|
old_size,
|
|
|
|
new_size);
|
|
|
|
return reinterpret_cast<uint8_t*>(new_ptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
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-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("%s expects argument 'buffer' to be non-null.",
|
|
|
|
CURRENT_FUNC);
|
2011-12-06 00:34:49 +00:00
|
|
|
}
|
|
|
|
if (size == NULL) {
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("%s expects argument 'size' to be non-null.",
|
|
|
|
CURRENT_FUNC);
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
|
|
|
const char* msg = CheckIsolateState(isolate,
|
|
|
|
ClassFinalizer::kGeneratingSnapshot);
|
|
|
|
if (msg != NULL) {
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError(msg);
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
|
|
|
// Since this is only a snapshot the root library should not be set.
|
|
|
|
isolate->object_store()->set_root_library(Library::Handle());
|
2011-12-06 00:34:49 +00:00
|
|
|
SnapshotWriter writer(Snapshot::kFull, buffer, ApiAllocator);
|
2011-11-22 19:42:38 +00:00
|
|
|
writer.WriteFullSnapshot();
|
2011-12-21 19:37:37 +00:00
|
|
|
*size = writer.BytesWritten();
|
2011-12-06 00:34:49 +00:00
|
|
|
return Api::Success();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
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-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("%s expects argument 'buffer' to be non-null.",
|
|
|
|
CURRENT_FUNC);
|
2011-12-06 00:34:49 +00:00
|
|
|
}
|
|
|
|
if (size == NULL) {
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("%s expects argument 'size' to be non-null.",
|
|
|
|
CURRENT_FUNC);
|
2011-12-06 00:34:49 +00:00
|
|
|
}
|
|
|
|
const char* msg = CheckIsolateState(isolate);
|
|
|
|
if (msg != NULL) {
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError(msg);
|
2011-12-06 00:34:49 +00:00
|
|
|
}
|
2011-12-20 02:04:24 +00:00
|
|
|
Library& library = Library::Handle(isolate->object_store()->root_library());
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
ScriptSnapshotWriter writer(buffer, ApiAllocator);
|
|
|
|
writer.WriteScriptSnapshot(library);
|
2011-12-21 19:37:37 +00:00
|
|
|
*size = writer.BytesWritten();
|
2011-11-22 19:42:38 +00:00
|
|
|
return Api::Success();
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-12-14 18:27:58 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_RunLoop() {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
2012-02-01 23:39:28 +00:00
|
|
|
|
|
|
|
LongJump* base = isolate->long_jump_base();
|
|
|
|
LongJump jump;
|
|
|
|
Dart_Handle result;
|
|
|
|
isolate->set_long_jump_base(&jump);
|
|
|
|
if (setjmp(*jump.Set()) == 0) {
|
|
|
|
const Object& obj = Object::Handle(isolate->StandardRunLoop());
|
|
|
|
if (obj.IsError()) {
|
|
|
|
result = Api::NewLocalHandle(obj);
|
|
|
|
} else {
|
|
|
|
ASSERT(obj.IsNull());
|
|
|
|
result = Api::Success();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
SetupErrorResult(&result);
|
2011-12-14 18:27:58 +00:00
|
|
|
}
|
2012-02-01 23:39:28 +00:00
|
|
|
isolate->set_long_jump_base(base);
|
|
|
|
return result;
|
2011-12-14 18:27:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-10-18 17:54:07 +00:00
|
|
|
static RawInstance* DeserializeMessage(void* data) {
|
|
|
|
// Create a snapshot object using the buffer.
|
|
|
|
const Snapshot* snapshot = Snapshot::SetupFromBuffer(data);
|
2011-12-06 00:34:49 +00:00
|
|
|
ASSERT(snapshot->IsMessageSnapshot());
|
2011-10-18 17:54:07 +00:00
|
|
|
|
|
|
|
// Read object back from the snapshot.
|
2012-01-10 18:47:38 +00:00
|
|
|
SnapshotReader reader(snapshot, Isolate::Current());
|
2011-10-18 17:54:07 +00:00
|
|
|
Instance& instance = Instance::Handle();
|
|
|
|
instance ^= reader.ReadObject();
|
|
|
|
return instance.raw();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-01-24 19:31:01 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_HandleMessage() {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
// Process all OOB messages and at most one normal message.
|
|
|
|
Message* message = NULL;
|
|
|
|
Message::Priority priority = Message::kNormalPriority;
|
|
|
|
do {
|
|
|
|
DARTSCOPE(isolate);
|
2012-02-01 18:53:40 +00:00
|
|
|
message = isolate->message_handler()->queue()->DequeueNoWait();
|
2012-01-24 19:31:01 +00:00
|
|
|
if (message == NULL) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
priority = message->priority();
|
|
|
|
if (priority == Message::kOOBPriority) {
|
|
|
|
// TODO(turnidge): Out of band messages will not go through the
|
|
|
|
// regular message handler. Instead they will be dispatched to
|
|
|
|
// special vm code. Implement.
|
|
|
|
UNIMPLEMENTED();
|
|
|
|
}
|
|
|
|
const Instance& msg =
|
|
|
|
Instance::Handle(DeserializeMessage(message->data()));
|
|
|
|
const Object& result = Object::Handle(
|
|
|
|
DartLibraryCalls::HandleMessage(
|
|
|
|
message->dest_port(), message->reply_port(), msg));
|
|
|
|
delete message;
|
|
|
|
if (result.IsError()) {
|
|
|
|
return Api::NewLocalHandle(result);
|
|
|
|
}
|
|
|
|
ASSERT(result.IsNull());
|
|
|
|
} while (priority >= Message::kOOBPriority);
|
2011-11-11 19:31:04 +00:00
|
|
|
return Api::Success();
|
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;
|
|
|
|
MessageWriter writer(&buffer, &allocator);
|
2011-10-05 05:20:07 +00:00
|
|
|
|
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(
|
|
|
|
port_id, Message::kIllegalPort, buffer, Message::kNormalPriority));
|
2011-10-05 05:20:07 +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);
|
2011-11-22 19:42:38 +00:00
|
|
|
const Object& object = Object::Handle(Api::UnwrapHandle(handle));
|
|
|
|
uint8_t* data = NULL;
|
2011-12-06 00:34:49 +00:00
|
|
|
SnapshotWriter writer(Snapshot::kMessage, &data, &allocator);
|
2011-11-22 19:42:38 +00:00
|
|
|
writer.WriteObject(object.raw());
|
|
|
|
writer.FinalizeBuffer();
|
2012-01-24 19:31:01 +00:00
|
|
|
return PortMap::PostMessage(new Message(
|
|
|
|
port_id, Message::kIllegalPort, data, 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) {
|
|
|
|
OS::PrintErr("%s expects argument 'handler' to be non-null.", CURRENT_FUNC);
|
|
|
|
return kIllegalPort;
|
|
|
|
}
|
|
|
|
// 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);
|
|
|
|
nmh->StartWorker();
|
|
|
|
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);
|
|
|
|
const String& class_name = String::Handle(String::NewSymbol("SendPortImpl"));
|
|
|
|
const String& function_name = String::Handle(String::NewSymbol("_create"));
|
|
|
|
const int kNumArguments = 1;
|
|
|
|
const Array& kNoArgumentNames = Array::Handle();
|
|
|
|
// TODO(turnidge): Consider adding a helper function to make
|
|
|
|
// function resolution by class name and function name more concise.
|
|
|
|
const Function& function = Function::Handle(
|
|
|
|
Resolver::ResolveStatic(Library::Handle(Library::CoreLibrary()),
|
|
|
|
class_name,
|
|
|
|
function_name,
|
|
|
|
kNumArguments,
|
|
|
|
kNoArgumentNames,
|
|
|
|
Resolver::kIsQualified));
|
|
|
|
GrowableArray<const Object*> arguments(kNumArguments);
|
|
|
|
arguments.Add(&Integer::Handle(Integer::New(port_id)));
|
2012-02-01 23:39:28 +00:00
|
|
|
Dart_Handle result;
|
|
|
|
InvokeStatic(isolate, function, arguments, &result);
|
|
|
|
return result;
|
2011-11-29 21:55:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_GetReceivePort(Dart_Port port_id) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
const String& class_name =
|
|
|
|
String::Handle(String::NewSymbol("ReceivePortImpl"));
|
|
|
|
const String& function_name =
|
|
|
|
String::Handle(String::NewSymbol("_get_or_create"));
|
|
|
|
const int kNumArguments = 1;
|
|
|
|
const Array& kNoArgumentNames = Array::Handle();
|
|
|
|
const Function& function = Function::Handle(
|
|
|
|
Resolver::ResolveStatic(Library::Handle(Library::CoreLibrary()),
|
|
|
|
class_name,
|
|
|
|
function_name,
|
|
|
|
kNumArguments,
|
|
|
|
kNoArgumentNames,
|
|
|
|
Resolver::kIsQualified));
|
|
|
|
GrowableArray<const Object*> arguments(kNumArguments);
|
|
|
|
arguments.Add(&Integer::Handle(Integer::New(port_id)));
|
2012-02-01 23:39:28 +00:00
|
|
|
Dart_Handle result;
|
|
|
|
InvokeStatic(isolate, function, arguments, &result);
|
|
|
|
return result;
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
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() {
|
2011-12-01 19:17:10 +00:00
|
|
|
CHECK_ISOLATE_SCOPE(Isolate::Current());
|
2011-11-05 00:09:36 +00:00
|
|
|
return Api::Null();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-10-05 05:20:07 +00:00
|
|
|
DART_EXPORT bool Dart_IsNull(Dart_Handle object) {
|
2011-11-12 05:55:22 +00:00
|
|
|
DARTSCOPE(Isolate::Current());
|
2011-10-05 05:20:07 +00:00
|
|
|
const Object& obj = Object::Handle(Api::UnwrapHandle(object));
|
|
|
|
return obj.IsNull();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-08 19:18:22 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_ObjectEquals(Dart_Handle obj1, Dart_Handle obj2,
|
|
|
|
bool* value) {
|
2011-11-12 05:55:22 +00:00
|
|
|
DARTSCOPE(Isolate::Current());
|
2011-10-05 05:20:07 +00:00
|
|
|
const Instance& expected = Instance::CheckedHandle(Api::UnwrapHandle(obj1));
|
|
|
|
const Instance& actual = Instance::CheckedHandle(Api::UnwrapHandle(obj2));
|
2012-02-01 23:39:28 +00:00
|
|
|
const Instance& result =
|
|
|
|
Instance::Handle(DartLibraryCalls::Equals(expected, actual));
|
2011-10-05 05:20:07 +00:00
|
|
|
if (result.IsBool()) {
|
|
|
|
Bool& b = Bool::Handle();
|
|
|
|
b ^= result.raw();
|
2011-10-26 20:38:41 +00:00
|
|
|
*value = b.value();
|
|
|
|
return Api::Success();
|
2012-01-10 21:42:21 +00:00
|
|
|
} else if (result.IsError()) {
|
|
|
|
return Api::NewLocalHandle(result);
|
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);
|
2011-10-05 05:20:07 +00:00
|
|
|
const Class& cls = Class::CheckedHandle(Api::UnwrapHandle(clazz));
|
|
|
|
if (cls.IsNull()) {
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("instanceof check against null class");
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
const Object& obj = Object::Handle(Api::UnwrapHandle(object));
|
|
|
|
Instance& instance = Instance::Handle();
|
|
|
|
instance ^= obj.raw();
|
|
|
|
// 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-01-10 21:42:21 +00:00
|
|
|
return Api::NewError(msg);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
const Type& type = Type::Handle(Type::NewNonParameterizedType(cls));
|
2011-11-24 00:26:18 +00:00
|
|
|
*value = instance.IsInstanceOf(type, TypeArguments::Handle());
|
2011-10-26 20:38:41 +00:00
|
|
|
return Api::Success();
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
// --- Numbers ----
|
|
|
|
|
|
|
|
|
2011-10-05 05:20:07 +00:00
|
|
|
// TODO(iposva): The argument should be an instance.
|
|
|
|
DART_EXPORT bool Dart_IsNumber(Dart_Handle object) {
|
2011-11-12 05:55:22 +00:00
|
|
|
DARTSCOPE(Isolate::Current());
|
2011-10-05 05:20:07 +00:00
|
|
|
const Object& obj = Object::Handle(Api::UnwrapHandle(object));
|
|
|
|
return obj.IsNumber();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
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) {
|
2011-11-12 05:55:22 +00:00
|
|
|
DARTSCOPE(Isolate::Current());
|
2011-10-05 05:20:07 +00:00
|
|
|
const Object& obj = Object::Handle(Api::UnwrapHandle(object));
|
|
|
|
return obj.IsInteger();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_IntegerFitsIntoInt64(Dart_Handle integer,
|
|
|
|
bool* fits) {
|
|
|
|
DARTSCOPE(Isolate::Current());
|
2011-12-09 17:25:44 +00:00
|
|
|
const Integer& int_obj = Api::UnwrapIntegerHandle(integer);
|
|
|
|
if (int_obj.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(integer, Integer);
|
|
|
|
}
|
|
|
|
if (int_obj.IsSmi() || int_obj.IsMint()) {
|
2011-11-22 19:42:38 +00:00
|
|
|
*fits = true;
|
2011-12-09 17:25:44 +00:00
|
|
|
} else {
|
|
|
|
ASSERT(int_obj.IsBigint());
|
2011-11-22 19:42:38 +00:00
|
|
|
#if defined(DEBUG)
|
|
|
|
Bigint& bigint = Bigint::Handle();
|
2011-12-09 17:25:44 +00:00
|
|
|
bigint ^= int_obj.raw();
|
2011-11-22 19:42:38 +00:00
|
|
|
ASSERT(!BigintOperations::FitsIntoInt64(bigint));
|
|
|
|
#endif
|
|
|
|
*fits = false;
|
|
|
|
}
|
2011-12-09 17:25:44 +00:00
|
|
|
return Api::Success();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_IntegerFitsIntoUint64(Dart_Handle integer,
|
|
|
|
bool* fits) {
|
|
|
|
DARTSCOPE(Isolate::Current());
|
|
|
|
const Integer& int_obj = Api::UnwrapIntegerHandle(integer);
|
|
|
|
if (int_obj.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(integer, Integer);
|
|
|
|
}
|
|
|
|
if (int_obj.IsSmi() || int_obj.IsMint()) {
|
|
|
|
*fits = !int_obj.IsNegative();
|
|
|
|
} else {
|
|
|
|
ASSERT(int_obj.IsBigint());
|
|
|
|
Bigint& bigint = Bigint::Handle();
|
|
|
|
bigint ^= int_obj.raw();
|
|
|
|
*fits = BigintOperations::FitsIntoUint64(bigint);
|
|
|
|
}
|
|
|
|
return Api::Success();
|
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) {
|
2011-11-12 05:55:22 +00:00
|
|
|
DARTSCOPE(Isolate::Current());
|
2011-10-05 05:20:07 +00:00
|
|
|
const Integer& obj = Integer::Handle(Integer::New(value));
|
|
|
|
return Api::NewLocalHandle(obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_NewIntegerFromHexCString(const char* str) {
|
2011-11-12 05:55:22 +00:00
|
|
|
DARTSCOPE(Isolate::Current());
|
2011-10-05 05:20:07 +00:00
|
|
|
const String& str_obj = String::Handle(String::New(str));
|
|
|
|
const Integer& obj = Integer::Handle(Integer::New(str_obj));
|
|
|
|
return Api::NewLocalHandle(obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-12-09 17:25:44 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_IntegerToInt64(Dart_Handle integer,
|
|
|
|
int64_t* value) {
|
2011-11-12 05:55:22 +00:00
|
|
|
DARTSCOPE(Isolate::Current());
|
2011-12-09 17:25:44 +00:00
|
|
|
const Integer& int_obj = Api::UnwrapIntegerHandle(integer);
|
|
|
|
if (int_obj.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(integer, Integer);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
2011-12-09 17:25:44 +00:00
|
|
|
if (int_obj.IsSmi() || int_obj.IsMint()) {
|
|
|
|
*value = int_obj.AsInt64Value();
|
|
|
|
return Api::Success();
|
|
|
|
} else {
|
|
|
|
ASSERT(int_obj.IsBigint());
|
2011-10-05 05:20:07 +00:00
|
|
|
Bigint& bigint = Bigint::Handle();
|
2011-12-09 17:25:44 +00:00
|
|
|
bigint ^= int_obj.raw();
|
2011-10-05 05:20:07 +00:00
|
|
|
if (BigintOperations::FitsIntoInt64(bigint)) {
|
2011-10-26 20:38:41 +00:00
|
|
|
*value = BigintOperations::ToInt64(bigint);
|
|
|
|
return Api::Success();
|
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) {
|
2011-11-12 05:55:22 +00:00
|
|
|
DARTSCOPE(Isolate::Current());
|
2011-12-09 17:25:44 +00:00
|
|
|
const Integer& int_obj = Api::UnwrapIntegerHandle(integer);
|
|
|
|
if (int_obj.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(integer, Integer);
|
|
|
|
}
|
|
|
|
if (int_obj.IsSmi() || int_obj.IsMint()) {
|
|
|
|
if (!int_obj.IsNegative()) {
|
|
|
|
*value = int_obj.AsInt64Value();
|
|
|
|
return Api::Success();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ASSERT(int_obj.IsBigint());
|
|
|
|
Bigint& bigint = Bigint::Handle();
|
|
|
|
bigint ^= int_obj.raw();
|
|
|
|
if (BigintOperations::FitsIntoUint64(bigint)) {
|
|
|
|
*value = BigintOperations::ToUint64(bigint);
|
|
|
|
return Api::Success();
|
|
|
|
}
|
|
|
|
}
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_IntegerToHexCString(Dart_Handle integer,
|
|
|
|
const char** value) {
|
|
|
|
DARTSCOPE(Isolate::Current());
|
|
|
|
const Integer& int_obj = Api::UnwrapIntegerHandle(integer);
|
|
|
|
if (int_obj.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(integer, Integer);
|
|
|
|
}
|
2011-10-26 20:38:41 +00:00
|
|
|
Bigint& bigint = Bigint::Handle();
|
2011-12-09 17:25:44 +00:00
|
|
|
if (int_obj.IsSmi() || int_obj.IsMint()) {
|
|
|
|
bigint ^= BigintOperations::NewFromInt64(int_obj.AsInt64Value());
|
2011-10-26 20:38:41 +00:00
|
|
|
*value = BigintOperations::ToHexCString(bigint, &Api::Allocate);
|
2011-12-09 17:25:44 +00:00
|
|
|
} else {
|
|
|
|
ASSERT(int_obj.IsBigint());
|
|
|
|
bigint ^= int_obj.raw();
|
2011-10-26 20:38:41 +00:00
|
|
|
*value = BigintOperations::ToHexCString(bigint, &Api::Allocate);
|
|
|
|
}
|
2011-12-09 17:25:44 +00:00
|
|
|
return Api::Success();
|
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() {
|
2011-12-01 19:17:10 +00:00
|
|
|
CHECK_ISOLATE_SCOPE(Isolate::Current());
|
2011-11-05 00:09:36 +00:00
|
|
|
return Api::True();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_False() {
|
2011-12-01 19:17:10 +00:00
|
|
|
CHECK_ISOLATE_SCOPE(Isolate::Current());
|
2011-11-05 00:09:36 +00:00
|
|
|
return Api::False();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-10-05 05:20:07 +00:00
|
|
|
DART_EXPORT bool Dart_IsBoolean(Dart_Handle object) {
|
2011-11-12 05:55:22 +00:00
|
|
|
DARTSCOPE(Isolate::Current());
|
2011-10-05 05:20:07 +00:00
|
|
|
const Object& obj = Object::Handle(Api::UnwrapHandle(object));
|
|
|
|
return obj.IsBool();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_NewBoolean(bool value) {
|
2011-12-01 19:17:10 +00:00
|
|
|
CHECK_ISOLATE_SCOPE(Isolate::Current());
|
2011-11-05 00:09:36 +00:00
|
|
|
return value ? Api::True() : Api::False();
|
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) {
|
2011-11-12 05:55:22 +00:00
|
|
|
DARTSCOPE(Isolate::Current());
|
2011-12-08 23:50:40 +00:00
|
|
|
const Bool& obj = Api::UnwrapBoolHandle(boolean_obj);
|
|
|
|
if (obj.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(boolean_obj, Bool);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
2011-12-08 23:50:40 +00:00
|
|
|
*value = obj.value();
|
|
|
|
return Api::Success();
|
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) {
|
2011-11-12 05:55:22 +00:00
|
|
|
DARTSCOPE(Isolate::Current());
|
2011-10-05 05:20:07 +00:00
|
|
|
const Object& obj = Object::Handle(Api::UnwrapHandle(object));
|
|
|
|
return obj.IsDouble();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_NewDouble(double value) {
|
2011-11-12 05:55:22 +00:00
|
|
|
DARTSCOPE(Isolate::Current());
|
2011-10-05 05:20:07 +00:00
|
|
|
const Double& obj = Double::Handle(Double::New(value));
|
|
|
|
return Api::NewLocalHandle(obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-12-08 23:50:40 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_DoubleValue(Dart_Handle double_obj,
|
|
|
|
double* value) {
|
2011-11-12 05:55:22 +00:00
|
|
|
DARTSCOPE(Isolate::Current());
|
2011-12-08 23:50:40 +00:00
|
|
|
const Double& obj = Api::UnwrapDoubleHandle(double_obj);
|
|
|
|
if (obj.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(double_obj, Double);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
2011-12-08 23:50:40 +00:00
|
|
|
*value = obj.value();
|
|
|
|
return Api::Success();
|
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) {
|
2011-11-12 05:55:22 +00:00
|
|
|
DARTSCOPE(Isolate::Current());
|
2011-10-05 05:20:07 +00:00
|
|
|
const Object& obj = Object::Handle(Api::UnwrapHandle(object));
|
|
|
|
return obj.IsString();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
DART_EXPORT bool Dart_IsString8(Dart_Handle object) {
|
|
|
|
DARTSCOPE(Isolate::Current());
|
|
|
|
const Object& obj = Object::Handle(Api::UnwrapHandle(object));
|
|
|
|
return obj.IsOneByteString() || obj.IsExternalOneByteString();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT bool Dart_IsString16(Dart_Handle object) {
|
|
|
|
DARTSCOPE(Isolate::Current());
|
|
|
|
const Object& obj = Object::Handle(Api::UnwrapHandle(object));
|
|
|
|
return (obj.IsOneByteString() || obj.IsExternalOneByteString() ||
|
|
|
|
obj.IsTwoByteString() || obj.IsExternalTwoByteString());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-10-26 20:38:41 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_StringLength(Dart_Handle str, intptr_t* len) {
|
2011-11-12 05:55:22 +00:00
|
|
|
DARTSCOPE(Isolate::Current());
|
2011-10-05 05:20:07 +00:00
|
|
|
const Object& obj = Object::Handle(Api::UnwrapHandle(str));
|
|
|
|
if (obj.IsString()) {
|
|
|
|
String& string_obj = String::Handle();
|
|
|
|
string_obj ^= obj.raw();
|
2011-10-26 20:38:41 +00:00
|
|
|
*len = string_obj.Length();
|
|
|
|
return Api::Success();
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("Object is not a String");
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_NewString(const char* str) {
|
2011-11-12 05:55:22 +00:00
|
|
|
DARTSCOPE(Isolate::Current());
|
2011-10-05 05:20:07 +00:00
|
|
|
const String& obj = String::Handle(String::New(str));
|
|
|
|
return Api::NewLocalHandle(obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_NewString8(const uint8_t* codepoints,
|
|
|
|
intptr_t length) {
|
2011-11-12 05:55:22 +00:00
|
|
|
DARTSCOPE(Isolate::Current());
|
2011-10-06 22:42:24 +00:00
|
|
|
const String& obj = String::Handle(String::New(codepoints, length));
|
2011-10-05 05:20:07 +00:00
|
|
|
return Api::NewLocalHandle(obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_NewString16(const uint16_t* codepoints,
|
|
|
|
intptr_t length) {
|
2011-11-12 05:55:22 +00:00
|
|
|
DARTSCOPE(Isolate::Current());
|
2011-10-05 05:20:07 +00:00
|
|
|
const String& obj = String::Handle(String::New(codepoints, length));
|
|
|
|
return Api::NewLocalHandle(obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_NewString32(const uint32_t* codepoints,
|
|
|
|
intptr_t length) {
|
2011-11-12 05:55:22 +00:00
|
|
|
DARTSCOPE(Isolate::Current());
|
2011-10-05 05:20:07 +00:00
|
|
|
const String& obj = String::Handle(String::New(codepoints, length));
|
|
|
|
return Api::NewLocalHandle(obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-12-05 17:55:01 +00:00
|
|
|
DART_EXPORT bool Dart_IsExternalString(Dart_Handle object) {
|
|
|
|
DARTSCOPE(Isolate::Current());
|
|
|
|
const String& str = Api::UnwrapStringHandle(object);
|
|
|
|
if (str.IsNull()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return str.IsExternal();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_ExternalStringGetPeer(Dart_Handle object,
|
|
|
|
void** peer) {
|
|
|
|
DARTSCOPE(Isolate::Current());
|
|
|
|
const String& str = Api::UnwrapStringHandle(object);
|
|
|
|
if (str.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(object, String);
|
|
|
|
}
|
|
|
|
if (!str.IsExternal()) {
|
2012-01-10 21:42:21 +00:00
|
|
|
return
|
|
|
|
Api::NewError("%s expects argument 'object' to be an external String.",
|
2011-12-05 17:55:01 +00:00
|
|
|
CURRENT_FUNC);
|
|
|
|
}
|
|
|
|
if (peer == NULL) {
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("%s expects argument 'peer' to be non-null.",
|
|
|
|
CURRENT_FUNC);
|
2011-12-05 17:55:01 +00:00
|
|
|
}
|
|
|
|
*peer = str.GetPeer();
|
|
|
|
return Api::Success();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-21 19:47:32 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_NewExternalString8(const uint8_t* codepoints,
|
2011-11-19 00:33:23 +00:00
|
|
|
intptr_t length,
|
|
|
|
void* peer,
|
|
|
|
Dart_PeerFinalizer callback) {
|
|
|
|
DARTSCOPE(Isolate::Current());
|
|
|
|
const String& obj =
|
|
|
|
String::Handle(String::NewExternal(codepoints, length, peer, callback));
|
|
|
|
return Api::NewLocalHandle(obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-21 19:47:32 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_NewExternalString16(const uint16_t* codepoints,
|
2011-11-19 00:33:23 +00:00
|
|
|
intptr_t length,
|
|
|
|
void* peer,
|
|
|
|
Dart_PeerFinalizer callback) {
|
|
|
|
DARTSCOPE(Isolate::Current());
|
|
|
|
const String& obj =
|
|
|
|
String::Handle(String::NewExternal(codepoints, length, peer, callback));
|
|
|
|
return Api::NewLocalHandle(obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-21 19:47:32 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_NewExternalString32(const uint32_t* codepoints,
|
2011-11-19 00:33:23 +00:00
|
|
|
intptr_t length,
|
|
|
|
void* peer,
|
|
|
|
Dart_PeerFinalizer callback) {
|
|
|
|
DARTSCOPE(Isolate::Current());
|
|
|
|
const String& obj =
|
|
|
|
String::Handle(String::NewExternal(codepoints, length, peer, callback));
|
|
|
|
return Api::NewLocalHandle(obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-10-26 20:38:41 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_StringGet8(Dart_Handle str,
|
2011-10-05 05:20:07 +00:00
|
|
|
uint8_t* codepoints,
|
2011-10-26 20:38:41 +00:00
|
|
|
intptr_t* length) {
|
2011-11-12 05:55:22 +00:00
|
|
|
DARTSCOPE(Isolate::Current());
|
2011-10-05 05:20:07 +00:00
|
|
|
const Object& obj = Object::Handle(Api::UnwrapHandle(str));
|
2011-11-19 00:33:23 +00:00
|
|
|
if (obj.IsString()) {
|
|
|
|
String& string_obj = String::Handle();
|
2011-10-05 05:20:07 +00:00
|
|
|
string_obj ^= obj.raw();
|
2011-11-19 00:33:23 +00:00
|
|
|
if (string_obj.CharSize() == String::kOneByteChar) {
|
|
|
|
intptr_t str_len = string_obj.Length();
|
|
|
|
intptr_t copy_len = (str_len > *length) ? *length : str_len;
|
|
|
|
for (intptr_t i = 0; i < copy_len; i++) {
|
|
|
|
codepoints[i] = static_cast<uint8_t>(string_obj.CharAt(i));
|
|
|
|
}
|
|
|
|
*length= copy_len;
|
|
|
|
return Api::Success();
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
}
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError(obj.IsString()
|
|
|
|
? "Object is not a String8"
|
|
|
|
: "Object is not a String");
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-10-26 20:38:41 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_StringGet16(Dart_Handle str,
|
2011-10-05 05:20:07 +00:00
|
|
|
uint16_t* codepoints,
|
2011-10-26 20:38:41 +00:00
|
|
|
intptr_t* length) {
|
2011-11-12 05:55:22 +00:00
|
|
|
DARTSCOPE(Isolate::Current());
|
2011-10-05 05:20:07 +00:00
|
|
|
const Object& obj = Object::Handle(Api::UnwrapHandle(str));
|
2011-11-19 00:33:23 +00:00
|
|
|
if (obj.IsString()) {
|
2011-10-05 05:20:07 +00:00
|
|
|
String& string_obj = String::Handle();
|
|
|
|
string_obj ^= obj.raw();
|
2011-11-19 00:33:23 +00:00
|
|
|
if (string_obj.CharSize() <= String::kTwoByteChar) {
|
|
|
|
intptr_t str_len = string_obj.Length();
|
|
|
|
intptr_t copy_len = (str_len > *length) ? *length : str_len;
|
|
|
|
for (intptr_t i = 0; i < copy_len; i++) {
|
|
|
|
codepoints[i] = static_cast<uint16_t>(string_obj.CharAt(i));
|
|
|
|
}
|
|
|
|
*length = copy_len;
|
|
|
|
return Api::Success();
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
}
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError(obj.IsString()
|
|
|
|
? "Object is not a String16"
|
|
|
|
: "Object is not a String");
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-10-26 20:38:41 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_StringGet32(Dart_Handle str,
|
2011-10-05 05:20:07 +00:00
|
|
|
uint32_t* codepoints,
|
2011-10-26 20:38:41 +00:00
|
|
|
intptr_t* length) {
|
2011-11-12 05:55:22 +00:00
|
|
|
DARTSCOPE(Isolate::Current());
|
2011-10-05 05:20:07 +00:00
|
|
|
const Object& obj = Object::Handle(Api::UnwrapHandle(str));
|
|
|
|
if (obj.IsString()) {
|
|
|
|
String& string_obj = String::Handle();
|
|
|
|
string_obj ^= obj.raw();
|
|
|
|
intptr_t str_len = string_obj.Length();
|
2011-10-26 20:38:41 +00:00
|
|
|
intptr_t copy_len = (str_len > *length) ? *length : str_len;
|
2011-10-05 05:20:07 +00:00
|
|
|
for (intptr_t i = 0; i < copy_len; i++) {
|
|
|
|
codepoints[i] = static_cast<uint32_t>(string_obj.CharAt(i));
|
|
|
|
}
|
2011-10-26 20:38:41 +00:00
|
|
|
*length = copy_len;
|
|
|
|
return Api::Success();
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("Object is not a String");
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-10-26 20:38:41 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_StringToCString(Dart_Handle object,
|
|
|
|
const char** result) {
|
2011-11-12 05:55:22 +00:00
|
|
|
DARTSCOPE(Isolate::Current());
|
2011-10-05 05:20:07 +00:00
|
|
|
const Object& obj = Object::Handle(Api::UnwrapHandle(object));
|
|
|
|
if (obj.IsString()) {
|
|
|
|
const char* string_value = obj.ToCString();
|
|
|
|
intptr_t string_length = strlen(string_value);
|
2011-10-26 20:38:41 +00:00
|
|
|
char* res = reinterpret_cast<char*>(Api::Allocate(string_length + 1));
|
|
|
|
if (res == NULL) {
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("Unable to allocate memory");
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
2011-10-26 20:38:41 +00:00
|
|
|
strncpy(res, string_value, string_length + 1);
|
|
|
|
ASSERT(res[string_length] == '\0');
|
|
|
|
*result = res;
|
|
|
|
return Api::Success();
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("Object is not a String");
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
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()) {
|
|
|
|
Instance& instance = Instance::Handle();
|
|
|
|
instance ^= obj.raw();
|
|
|
|
const Type& type = Type::Handle(isolate->object_store()->list_interface());
|
2011-11-24 00:26:18 +00:00
|
|
|
if (instance.IsInstanceOf(type, TypeArguments::Handle())) {
|
|
|
|
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) {
|
2011-11-12 05:55:22 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
2011-10-05 05:20:07 +00:00
|
|
|
const Object& obj = Object::Handle(Api::UnwrapHandle(object));
|
2011-10-31 21:08:39 +00:00
|
|
|
// TODO(5526318): Make access to GrowableObjectArray more efficient.
|
2011-11-04 12:25:53 +00:00
|
|
|
return (obj.IsArray() ||
|
2011-11-12 05:55:22 +00:00
|
|
|
(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) {
|
2011-11-12 05:55:22 +00:00
|
|
|
DARTSCOPE(Isolate::Current());
|
2011-10-05 05:20:07 +00:00
|
|
|
const Array& obj = Array::Handle(Array::New(length));
|
|
|
|
return Api::NewLocalHandle(obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
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);
|
2011-11-04 12:25:53 +00:00
|
|
|
const Object& obj = Object::Handle(Api::UnwrapHandle(list));
|
2012-02-01 21:48:27 +00:00
|
|
|
if (obj.IsByteArray()) {
|
|
|
|
ByteArray& byte_array = ByteArray::Handle();
|
|
|
|
byte_array ^= obj.raw();
|
|
|
|
*len = byte_array.Length();
|
|
|
|
return Api::Success();
|
|
|
|
}
|
2011-10-05 05:20:07 +00:00
|
|
|
if (obj.IsArray()) {
|
|
|
|
Array& array_obj = Array::Handle();
|
|
|
|
array_obj ^= obj.raw();
|
2011-10-26 20:38:41 +00:00
|
|
|
*len = array_obj.Length();
|
|
|
|
return Api::Success();
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
2011-10-31 21:08:39 +00:00
|
|
|
// TODO(5526318): Make access to GrowableObjectArray more efficient.
|
|
|
|
// Now check and handle a dart object that implements the List interface.
|
|
|
|
const Instance& instance = Instance::Handle(GetListInstance(isolate, obj));
|
2012-02-01 23:39:28 +00:00
|
|
|
if (!instance.IsNull()) {
|
|
|
|
String& name = String::Handle(String::New("length"));
|
|
|
|
name = Field::GetterName(name);
|
|
|
|
const Function& function = Function::Handle(
|
|
|
|
Resolver::ResolveDynamic(instance, name, 1, 0));
|
|
|
|
if (!function.IsNull()) {
|
|
|
|
GrowableArray<const Object*> args(0);
|
|
|
|
LongJump* base = isolate->long_jump_base();
|
|
|
|
LongJump jump;
|
|
|
|
isolate->set_long_jump_base(&jump);
|
|
|
|
Dart_Handle result;
|
|
|
|
if (setjmp(*jump.Set()) == 0) {
|
|
|
|
const Array& kNoArgumentNames = Array::Handle();
|
|
|
|
const Instance& retval = Instance::Handle(
|
|
|
|
DartEntry::InvokeDynamic(instance,
|
|
|
|
function,
|
|
|
|
args,
|
|
|
|
kNoArgumentNames));
|
|
|
|
result = Api::Success();
|
|
|
|
if (retval.IsSmi() || retval.IsMint()) {
|
|
|
|
Integer& integer = Integer::Handle();
|
|
|
|
integer ^= retval.raw();
|
|
|
|
*len = integer.AsInt64Value();
|
|
|
|
} else if (retval.IsBigint()) {
|
|
|
|
Bigint& bigint = Bigint::Handle();
|
|
|
|
bigint ^= retval.raw();
|
|
|
|
if (BigintOperations::FitsIntoInt64(bigint)) {
|
|
|
|
*len = BigintOperations::ToInt64(bigint);
|
|
|
|
} else {
|
|
|
|
result =
|
|
|
|
Api::NewError("Length of List object is greater than the "
|
|
|
|
"maximum value that 'len' parameter can hold");
|
|
|
|
}
|
|
|
|
} else if (retval.IsError()) {
|
|
|
|
result = Api::NewLocalHandle(retval);
|
|
|
|
} else {
|
|
|
|
result = Api::NewError("Length of List object is not an integer");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
SetupErrorResult(&result);
|
|
|
|
}
|
|
|
|
isolate->set_long_jump_base(base);
|
|
|
|
return result;
|
|
|
|
}
|
2011-10-31 21:08:39 +00:00
|
|
|
}
|
2012-02-01 23:39:28 +00:00
|
|
|
return Api::NewError("Object does not implement the 'List' inteface");
|
|
|
|
}
|
2011-10-31 21:08:39 +00:00
|
|
|
|
2012-02-01 23:39:28 +00:00
|
|
|
static RawObject* GetListAt(Isolate* isolate,
|
|
|
|
const Instance& instance,
|
|
|
|
const Integer& index,
|
|
|
|
const Function& function,
|
|
|
|
Dart_Handle* result) {
|
|
|
|
ASSERT(isolate != NULL);
|
|
|
|
ASSERT(result != NULL);
|
|
|
|
LongJump* base = isolate->long_jump_base();
|
|
|
|
LongJump jump;
|
|
|
|
isolate->set_long_jump_base(&jump);
|
|
|
|
if (setjmp(*jump.Set()) == 0) {
|
|
|
|
Instance& retval = Instance::Handle();
|
|
|
|
GrowableArray<const Object*> args(0);
|
|
|
|
args.Add(&index);
|
|
|
|
const Array& kNoArgumentNames = Array::Handle();
|
|
|
|
retval = DartEntry::InvokeDynamic(instance,
|
|
|
|
function,
|
|
|
|
args,
|
|
|
|
kNoArgumentNames);
|
|
|
|
if (retval.IsError()) {
|
|
|
|
*result = Api::NewLocalHandle(retval);
|
2011-10-31 21:08:39 +00:00
|
|
|
} else {
|
2012-02-01 23:39:28 +00:00
|
|
|
*result = Api::Success();
|
2011-10-31 21:08:39 +00:00
|
|
|
}
|
2012-02-01 23:39:28 +00:00
|
|
|
isolate->set_long_jump_base(base);
|
|
|
|
return retval.raw();
|
2011-10-31 21:08:39 +00:00
|
|
|
}
|
2012-02-01 23:39:28 +00:00
|
|
|
SetupErrorResult(result);
|
|
|
|
isolate->set_long_jump_base(base);
|
|
|
|
return Object::null();
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
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);
|
2011-11-04 12:25:53 +00:00
|
|
|
const Object& obj = Object::Handle(Api::UnwrapHandle(list));
|
2011-10-05 05:20:07 +00:00
|
|
|
if (obj.IsArray()) {
|
|
|
|
Array& array_obj = Array::Handle();
|
|
|
|
array_obj ^= obj.raw();
|
|
|
|
if ((index >= 0) && (index < array_obj.Length())) {
|
|
|
|
const Object& element = Object::Handle(array_obj.At(index));
|
2011-10-26 20:38:41 +00:00
|
|
|
return Api::NewLocalHandle(element);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("Invalid index passed in to access array element");
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
2011-10-31 21:08:39 +00:00
|
|
|
// TODO(5526318): Make access to GrowableObjectArray more efficient.
|
|
|
|
// Now check and handle a dart object that implements the List interface.
|
|
|
|
const Instance& instance = Instance::Handle(GetListInstance(isolate, obj));
|
|
|
|
if (!instance.IsNull()) {
|
|
|
|
String& name = String::Handle(String::New("[]"));
|
|
|
|
const Function& function = Function::Handle(
|
|
|
|
Resolver::ResolveDynamic(instance, name, 2, 0));
|
|
|
|
if (!function.IsNull()) {
|
2012-02-01 23:39:28 +00:00
|
|
|
Object& element = Object::Handle();
|
2011-10-31 21:08:39 +00:00
|
|
|
Integer& indexobj = Integer::Handle();
|
2012-02-01 23:39:28 +00:00
|
|
|
Dart_Handle result;
|
2011-10-31 21:08:39 +00:00
|
|
|
indexobj = Integer::New(index);
|
2012-02-01 23:39:28 +00:00
|
|
|
element = GetListAt(isolate, instance, indexobj, function, &result);
|
|
|
|
if (::Dart_IsError(result)) {
|
|
|
|
return result; // Error condition.
|
|
|
|
}
|
|
|
|
return Api::NewLocalHandle(element);
|
2011-10-31 21:08:39 +00:00
|
|
|
}
|
|
|
|
}
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("Object does not implement the 'List' interface");
|
2011-10-31 21:08:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-02-01 23:39:28 +00:00
|
|
|
static void SetListAt(Isolate* isolate,
|
|
|
|
const Instance& instance,
|
|
|
|
const Integer& index,
|
|
|
|
const Object& value,
|
|
|
|
const Function& function,
|
|
|
|
Dart_Handle* result) {
|
|
|
|
ASSERT(isolate != NULL);
|
|
|
|
ASSERT(result != NULL);
|
|
|
|
LongJump* base = isolate->long_jump_base();
|
|
|
|
LongJump jump;
|
|
|
|
isolate->set_long_jump_base(&jump);
|
|
|
|
if (setjmp(*jump.Set()) == 0) {
|
|
|
|
GrowableArray<const Object*> args(1);
|
|
|
|
args.Add(&index);
|
|
|
|
args.Add(&value);
|
|
|
|
Instance& retval = Instance::Handle();
|
|
|
|
const Array& kNoArgumentNames = Array::Handle();
|
|
|
|
retval = DartEntry::InvokeDynamic(instance,
|
|
|
|
function,
|
|
|
|
args,
|
|
|
|
kNoArgumentNames);
|
|
|
|
if (retval.IsError()) {
|
|
|
|
*result = Api::NewLocalHandle(retval);
|
|
|
|
} else {
|
|
|
|
*result = Api::Success();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
SetupErrorResult(result);
|
|
|
|
}
|
|
|
|
isolate->set_long_jump_base(base);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
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);
|
2011-11-04 12:25:53 +00:00
|
|
|
const Object& obj = Object::Handle(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
|
|
|
}
|
2011-10-05 05:20:07 +00:00
|
|
|
Array& array_obj = Array::Handle();
|
|
|
|
array_obj ^= obj.raw();
|
2011-11-22 19:42:38 +00:00
|
|
|
const Object& value_obj = Object::Handle(Api::UnwrapHandle(value));
|
|
|
|
if ((index >= 0) && (index < array_obj.Length())) {
|
|
|
|
array_obj.SetAt(index, value_obj);
|
|
|
|
return Api::Success();
|
|
|
|
}
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("Invalid index passed in to set array element");
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
|
|
|
// TODO(5526318): Make access to GrowableObjectArray more efficient.
|
|
|
|
// Now check and handle a dart object that implements the List interface.
|
|
|
|
const Instance& instance = Instance::Handle(GetListInstance(isolate, obj));
|
|
|
|
if (!instance.IsNull()) {
|
|
|
|
String& name = String::Handle(String::New("[]="));
|
|
|
|
const Function& function = Function::Handle(
|
|
|
|
Resolver::ResolveDynamic(instance, name, 3, 0));
|
|
|
|
if (!function.IsNull()) {
|
2012-02-01 23:39:28 +00:00
|
|
|
Dart_Handle result;
|
2011-11-22 19:42:38 +00:00
|
|
|
const Integer& index_obj = Integer::Handle(Integer::New(index));
|
|
|
|
const Object& value_obj = Object::Handle(Api::UnwrapHandle(value));
|
2012-02-01 23:39:28 +00:00
|
|
|
SetListAt(isolate, instance, index_obj, value_obj, function, &result);
|
|
|
|
return result;
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
|
|
|
}
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("Object does not implement the 'List' interface");
|
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);
|
|
|
|
const Object& obj = Object::Handle(Api::UnwrapHandle(list));
|
2012-02-01 21:48:27 +00:00
|
|
|
if (obj.IsByteArray()) {
|
|
|
|
ByteArray& byte_array = ByteArray::Handle();
|
|
|
|
byte_array ^= obj.raw();
|
|
|
|
if (Utils::RangeCheck(offset, length, byte_array.Length())) {
|
|
|
|
ByteArray::Copy(native_array, byte_array, offset, length);
|
|
|
|
return Api::Success();
|
|
|
|
}
|
|
|
|
return Api::NewError("Invalid length passed in to access list elements");
|
|
|
|
}
|
2011-11-22 19:42:38 +00:00
|
|
|
if (obj.IsArray()) {
|
|
|
|
Array& array_obj = Array::Handle();
|
|
|
|
array_obj ^= obj.raw();
|
2011-10-05 05:20:07 +00:00
|
|
|
if ((offset + length) <= array_obj.Length()) {
|
2011-11-22 19:42:38 +00:00
|
|
|
Object& element = Object::Handle();
|
|
|
|
Integer& integer = Integer::Handle();
|
2011-10-05 05:20:07 +00:00
|
|
|
for (int i = 0; i < length; i++) {
|
2011-11-22 19:42:38 +00:00
|
|
|
element = array_obj.At(offset + i);
|
|
|
|
if (!element.IsInteger()) {
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("%s expects the argument 'list' to be "
|
2011-11-22 19:42:38 +00:00
|
|
|
"a List of int", CURRENT_FUNC);
|
|
|
|
}
|
|
|
|
integer ^= element.raw();
|
|
|
|
native_array[i] = static_cast<uint8_t>(integer.AsInt64Value() & 0xff);
|
|
|
|
ASSERT(integer.AsInt64Value() <= 0xff);
|
|
|
|
// TODO(hpayer): value should always be smaller then 0xff. Add error
|
|
|
|
// handling.
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
2011-10-26 20:38:41 +00:00
|
|
|
return Api::Success();
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("Invalid length passed in to access array elements");
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
2011-10-31 21:08:39 +00:00
|
|
|
// TODO(5526318): Make access to GrowableObjectArray more efficient.
|
|
|
|
// Now check and handle a dart object that implements the List interface.
|
|
|
|
const Instance& instance = Instance::Handle(GetListInstance(isolate, obj));
|
|
|
|
if (!instance.IsNull()) {
|
2011-11-22 19:42:38 +00:00
|
|
|
String& name = String::Handle(String::New("[]"));
|
2011-10-31 21:08:39 +00:00
|
|
|
const Function& function = Function::Handle(
|
2011-11-22 19:42:38 +00:00
|
|
|
Resolver::ResolveDynamic(instance, name, 2, 0));
|
2011-10-31 21:08:39 +00:00
|
|
|
if (!function.IsNull()) {
|
2012-02-01 23:39:28 +00:00
|
|
|
Object& element = Object::Handle();
|
2011-11-22 19:42:38 +00:00
|
|
|
Integer& intobj = Integer::Handle();
|
2012-02-01 23:39:28 +00:00
|
|
|
Dart_Handle result;
|
2011-10-31 21:08:39 +00:00
|
|
|
for (int i = 0; i < length; i++) {
|
2011-11-22 19:42:38 +00:00
|
|
|
intobj = Integer::New(offset + i);
|
2012-02-01 23:39:28 +00:00
|
|
|
element = GetListAt(isolate, instance, intobj, function, &result);
|
|
|
|
if (::Dart_IsError(result)) {
|
|
|
|
return result; // Error condition.
|
2011-10-31 21:08:39 +00:00
|
|
|
}
|
2012-02-01 23:39:28 +00:00
|
|
|
if (!element.IsInteger()) {
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("%s expects the argument 'list' to be "
|
2012-02-01 23:39:28 +00:00
|
|
|
"a List of int", CURRENT_FUNC);
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
2012-02-01 23:39:28 +00:00
|
|
|
intobj ^= element.raw();
|
2011-11-22 19:42:38 +00:00
|
|
|
ASSERT(intobj.AsInt64Value() <= 0xff);
|
|
|
|
// TODO(hpayer): value should always be smaller then 0xff. Add error
|
|
|
|
// handling.
|
|
|
|
native_array[i] = static_cast<uint8_t>(intobj.AsInt64Value() & 0xff);
|
2011-10-31 21:08:39 +00:00
|
|
|
}
|
|
|
|
return Api::Success();
|
|
|
|
}
|
|
|
|
}
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("Object does not implement the 'List' interface");
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
2011-10-31 21:08:39 +00:00
|
|
|
|
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);
|
2011-11-04 12:25:53 +00:00
|
|
|
const Object& obj = Object::Handle(Api::UnwrapHandle(list));
|
2012-02-01 21:48:27 +00:00
|
|
|
if (obj.IsByteArray()) {
|
|
|
|
ByteArray& byte_array = ByteArray::Handle();
|
|
|
|
byte_array ^= obj.raw();
|
|
|
|
if (Utils::RangeCheck(offset, length, byte_array.Length())) {
|
|
|
|
ByteArray::Copy(byte_array, offset, native_array, length);
|
|
|
|
return Api::Success();
|
|
|
|
}
|
|
|
|
return Api::NewError("Invalid length passed in to set list elements");
|
|
|
|
}
|
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
|
|
|
}
|
2011-10-05 05:20:07 +00:00
|
|
|
Array& array_obj = Array::Handle();
|
|
|
|
array_obj ^= obj.raw();
|
2011-11-22 19:42:38 +00:00
|
|
|
Integer& integer = Integer::Handle();
|
|
|
|
if ((offset + length) <= array_obj.Length()) {
|
|
|
|
for (int i = 0; i < length; i++) {
|
|
|
|
integer = Integer::New(native_array[i]);
|
|
|
|
array_obj.SetAt(offset + i, integer);
|
|
|
|
}
|
2011-10-26 20:38:41 +00:00
|
|
|
return Api::Success();
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("Invalid length passed in to set array elements");
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
2011-10-31 21:08:39 +00:00
|
|
|
// TODO(5526318): Make access to GrowableObjectArray more efficient.
|
|
|
|
// Now check and handle a dart object that implements the List interface.
|
|
|
|
const Instance& instance = Instance::Handle(GetListInstance(isolate, obj));
|
2012-02-01 23:39:28 +00:00
|
|
|
Dart_Handle result;
|
2011-10-31 21:08:39 +00:00
|
|
|
if (!instance.IsNull()) {
|
|
|
|
String& name = String::Handle(String::New("[]="));
|
|
|
|
const Function& function = Function::Handle(
|
|
|
|
Resolver::ResolveDynamic(instance, name, 3, 0));
|
|
|
|
if (!function.IsNull()) {
|
2011-11-22 19:42:38 +00:00
|
|
|
Integer& indexobj = Integer::Handle();
|
|
|
|
Integer& valueobj = Integer::Handle();
|
|
|
|
for (int i = 0; i < length; i++) {
|
|
|
|
indexobj = Integer::New(offset + i);
|
|
|
|
valueobj = Integer::New(native_array[i]);
|
2012-02-01 23:39:28 +00:00
|
|
|
SetListAt(isolate, instance, indexobj, valueobj, function, &result);
|
|
|
|
if (::Dart_IsError(result)) {
|
|
|
|
return result; // Error condition.
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return Api::Success();
|
2011-10-31 21:08:39 +00:00
|
|
|
}
|
|
|
|
}
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("Object does not implement the 'List' interface");
|
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) {
|
|
|
|
DARTSCOPE(Isolate::Current());
|
|
|
|
const Object& obj = Object::Handle(Api::UnwrapHandle(object));
|
|
|
|
return obj.IsByteArray();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_NewByteArray(intptr_t length) {
|
|
|
|
DARTSCOPE(Isolate::Current());
|
|
|
|
const InternalByteArray& obj =
|
|
|
|
InternalByteArray::Handle(InternalByteArray::New(length));
|
|
|
|
return Api::NewLocalHandle(obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
// --- Closures ---
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT bool Dart_IsClosure(Dart_Handle object) {
|
|
|
|
DARTSCOPE(Isolate::Current());
|
|
|
|
const Object& obj = Object::Handle(Api::UnwrapHandle(object));
|
|
|
|
return obj.IsClosure();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-02-01 23:39:28 +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 InvokeClosure(Isolate* isolate,
|
|
|
|
const Closure& closure,
|
|
|
|
GrowableArray<const Object*>& args,
|
|
|
|
Dart_Handle* result) {
|
|
|
|
ASSERT(isolate != NULL);
|
|
|
|
LongJump* base = isolate->long_jump_base();
|
|
|
|
LongJump jump;
|
|
|
|
isolate->set_long_jump_base(&jump);
|
|
|
|
if (setjmp(*jump.Set()) == 0) {
|
|
|
|
const Array& kNoArgumentNames = Array::Handle();
|
|
|
|
const Instance& retval = Instance::Handle(
|
|
|
|
DartEntry::InvokeClosure(closure, args, kNoArgumentNames));
|
|
|
|
*result = Api::NewLocalHandle(retval);
|
|
|
|
} else {
|
|
|
|
SetupErrorResult(result);
|
|
|
|
}
|
|
|
|
isolate->set_long_jump_base(base);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
const Object& obj = Object::Handle(Api::UnwrapHandle(closure));
|
|
|
|
if (obj.IsNull()) {
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("Null object passed in to invoke closure");
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
|
|
|
if (!obj.IsClosure()) {
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("Invalid closure passed to invoke closure");
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
|
|
|
ASSERT(ClassFinalizer::AllClassesFinalized());
|
|
|
|
|
|
|
|
// Now try to invoke the closure.
|
|
|
|
Closure& closure_obj = Closure::Handle();
|
|
|
|
closure_obj ^= obj.raw();
|
2012-02-01 23:39:28 +00:00
|
|
|
Dart_Handle retval;
|
2011-11-22 19:42:38 +00:00
|
|
|
GrowableArray<const Object*> dart_arguments(number_of_arguments);
|
|
|
|
for (int i = 0; i < number_of_arguments; i++) {
|
|
|
|
const Object& arg = Object::Handle(Api::UnwrapHandle(arguments[i]));
|
|
|
|
dart_arguments.Add(&arg);
|
|
|
|
}
|
2012-02-01 23:39:28 +00:00
|
|
|
InvokeClosure(isolate, closure_obj, dart_arguments, &retval);
|
|
|
|
return retval;
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT int64_t Dart_ClosureSmrck(Dart_Handle object) {
|
|
|
|
DARTSCOPE(Isolate::Current());
|
|
|
|
const Closure& obj = Closure::CheckedHandle(Api::UnwrapHandle(object));
|
|
|
|
const Integer& smrck = Integer::Handle(obj.smrck());
|
|
|
|
return smrck.IsNull() ? 0 : smrck.AsInt64Value();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DART_EXPORT void Dart_ClosureSetSmrck(Dart_Handle object, int64_t value) {
|
|
|
|
DARTSCOPE(Isolate::Current());
|
|
|
|
const Closure& obj = Closure::CheckedHandle(Api::UnwrapHandle(object));
|
|
|
|
const Integer& smrck = Integer::Handle(Integer::New(value));
|
|
|
|
obj.set_smrck(smrck);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// --- Methods and Fields ---
|
|
|
|
|
|
|
|
|
2011-10-26 20:38:41 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_InvokeStatic(Dart_Handle library_in,
|
2011-10-05 05:20:07 +00:00
|
|
|
Dart_Handle class_name_in,
|
|
|
|
Dart_Handle function_name_in,
|
|
|
|
int number_of_arguments,
|
|
|
|
Dart_Handle* arguments) {
|
2011-11-12 05:55:22 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
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-01-10 21:42:21 +00:00
|
|
|
return Api::NewError(msg);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Now try to resolve and invoke the static function.
|
|
|
|
const Library& library =
|
|
|
|
Library::CheckedHandle(Api::UnwrapHandle(library_in));
|
|
|
|
if (library.IsNull()) {
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("No library specified");
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
const String& class_name =
|
|
|
|
String::CheckedHandle(Api::UnwrapHandle(class_name_in));
|
|
|
|
const String& function_name =
|
|
|
|
String::CheckedHandle(Api::UnwrapHandle(function_name_in));
|
|
|
|
const Function& function = Function::Handle(
|
|
|
|
Resolver::ResolveStatic(library,
|
|
|
|
class_name,
|
|
|
|
function_name,
|
|
|
|
number_of_arguments,
|
|
|
|
Array::Handle(), // Named arguments are not yet
|
|
|
|
// supported in the API.
|
|
|
|
Resolver::kIsQualified));
|
|
|
|
if (function.IsNull()) {
|
|
|
|
char* msg;
|
|
|
|
if (class_name.IsNull()) {
|
|
|
|
const char* format = "Unable to find entrypoint: %s()";
|
|
|
|
intptr_t length = OS::SNPrint(NULL, 0, format, function_name.ToCString());
|
|
|
|
msg = reinterpret_cast<char*>(Api::Allocate(length + 1));
|
|
|
|
OS::SNPrint(msg, (length + 1), format, function_name.ToCString());
|
|
|
|
} else {
|
|
|
|
const char* format = "Unable to find entrypoint: static %s.%s()";
|
|
|
|
intptr_t length = OS::SNPrint(NULL, 0, format,
|
|
|
|
class_name.ToCString(),
|
|
|
|
function_name.ToCString());
|
|
|
|
msg = reinterpret_cast<char*>(Api::Allocate(length + 1));
|
|
|
|
OS::SNPrint(msg, (length + 1), format,
|
|
|
|
class_name.ToCString(), function_name.ToCString());
|
|
|
|
}
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError(msg);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
GrowableArray<const Object*> dart_arguments(number_of_arguments);
|
|
|
|
for (int i = 0; i < number_of_arguments; i++) {
|
|
|
|
const Object& arg = Object::Handle(Api::UnwrapHandle(arguments[i]));
|
|
|
|
dart_arguments.Add(&arg);
|
|
|
|
}
|
2012-02-01 23:39:28 +00:00
|
|
|
Dart_Handle retval;
|
|
|
|
InvokeStatic(isolate, function, dart_arguments, &retval);
|
|
|
|
return retval;
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-10-26 20:38:41 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_InvokeDynamic(Dart_Handle object,
|
2011-10-05 05:20:07 +00:00
|
|
|
Dart_Handle function_name,
|
|
|
|
int number_of_arguments,
|
|
|
|
Dart_Handle* arguments) {
|
2011-11-12 05:55:22 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
2011-10-05 05:20:07 +00:00
|
|
|
const Object& obj = Object::Handle(Api::UnwrapHandle(object));
|
2011-10-06 07:46:45 +00:00
|
|
|
// Let the resolver figure out the correct target for null receiver.
|
|
|
|
// E.g., (null).toString() should execute correctly.
|
|
|
|
if (!obj.IsNull() && !obj.IsInstance()) {
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError(
|
2011-10-26 20:38:41 +00:00
|
|
|
"Invalid receiver (not instance) passed to invoke dynamic");
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
if (function_name == NULL) {
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("Invalid function name specified");
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
ASSERT(ClassFinalizer::AllClassesFinalized());
|
|
|
|
|
|
|
|
// Now try to resolve and invoke the dynamic function on this object.
|
|
|
|
Instance& receiver = Instance::Handle();
|
|
|
|
receiver ^= obj.raw();
|
|
|
|
const String& name = String::CheckedHandle(Api::UnwrapHandle(function_name));
|
|
|
|
const Function& function = Function::Handle(
|
|
|
|
Resolver::ResolveDynamic(receiver,
|
|
|
|
name,
|
|
|
|
(number_of_arguments + 1),
|
|
|
|
0)); // Named args not yet supported in API.
|
|
|
|
if (function.IsNull()) {
|
2011-10-05 16:27:07 +00:00
|
|
|
// TODO(5415268): Invoke noSuchMethod instead of failing.
|
|
|
|
OS::PrintErr("Unable to find instance function: %s\n", name.ToCString());
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("Unable to find instance function");
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
GrowableArray<const Object*> dart_arguments(number_of_arguments);
|
|
|
|
for (int i = 0; i < number_of_arguments; i++) {
|
|
|
|
const Object& arg = Object::Handle(Api::UnwrapHandle(arguments[i]));
|
|
|
|
dart_arguments.Add(&arg);
|
|
|
|
}
|
2012-02-01 23:39:28 +00:00
|
|
|
Dart_Handle retval;
|
|
|
|
InvokeDynamic(isolate, receiver, function, dart_arguments, &retval);
|
|
|
|
return retval;
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static const bool kGetter = true;
|
|
|
|
static const bool kSetter = false;
|
|
|
|
|
|
|
|
|
|
|
|
static bool UseGetterForStaticField(const Field& fld) {
|
|
|
|
if (fld.IsNull()) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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.
|
|
|
|
const Instance& value = Instance::Handle(fld.value());
|
|
|
|
ASSERT(value.raw() != Object::transition_sentinel());
|
|
|
|
return value.raw() == Object::sentinel();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-10-26 20:38:41 +00:00
|
|
|
static Dart_Handle LookupStaticField(Dart_Handle clazz,
|
2011-10-05 05:20:07 +00:00
|
|
|
Dart_Handle field_name,
|
|
|
|
bool is_getter) {
|
|
|
|
const Object& param1 = Object::Handle(Api::UnwrapHandle(clazz));
|
|
|
|
const Object& param2 = Object::Handle(Api::UnwrapHandle(field_name));
|
|
|
|
if (param1.IsNull() || !param1.IsClass()) {
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("Invalid class specified");
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
if (param2.IsNull() || !param2.IsString()) {
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("Invalid field name specified");
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
Class& cls = Class::Handle();
|
|
|
|
cls ^= param1.raw();
|
|
|
|
String& fld_name = String::Handle();
|
|
|
|
fld_name ^= param2.raw();
|
|
|
|
const Field& fld = Field::Handle(cls.LookupStaticField(fld_name));
|
|
|
|
if (is_getter && UseGetterForStaticField(fld)) {
|
|
|
|
const String& func_name = String::Handle(Field::GetterName(fld_name));
|
|
|
|
const Function& function =
|
|
|
|
Function::Handle(cls.LookupStaticFunction(func_name));
|
|
|
|
if (!function.IsNull()) {
|
2011-10-26 20:38:41 +00:00
|
|
|
return Api::NewLocalHandle(function);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("Specified field is not found in the class");
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
if (fld.IsNull()) {
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("Specified field is not found in the class");
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
2011-10-26 20:38:41 +00:00
|
|
|
return Api::NewLocalHandle(fld);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-10-26 20:38:41 +00:00
|
|
|
static Dart_Handle LookupInstanceField(const Object& object,
|
2011-10-05 05:20:07 +00:00
|
|
|
Dart_Handle name,
|
|
|
|
bool is_getter) {
|
|
|
|
const Object& param = Object::Handle(Api::UnwrapHandle(name));
|
|
|
|
if (param.IsNull() || !param.IsString()) {
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("Invalid field name specified");
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
String& field_name = String::Handle();
|
|
|
|
field_name ^= param.raw();
|
|
|
|
String& func_name = String::Handle();
|
|
|
|
Field& fld = Field::Handle();
|
|
|
|
Class& cls = Class::Handle(object.clazz());
|
|
|
|
while (!cls.IsNull()) {
|
|
|
|
fld = cls.LookupInstanceField(field_name);
|
|
|
|
if (!fld.IsNull()) {
|
|
|
|
if (!is_getter && fld.is_final()) {
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("Cannot set value of final fields");
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
2011-10-26 20:38:41 +00:00
|
|
|
func_name = (is_getter
|
|
|
|
? Field::GetterName(field_name)
|
|
|
|
: Field::SetterName(field_name));
|
2011-10-05 05:20:07 +00:00
|
|
|
const Function& function = Function::Handle(
|
|
|
|
cls.LookupDynamicFunction(func_name));
|
|
|
|
if (function.IsNull()) {
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("Unable to find accessor function in the class");
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
2011-10-26 20:38:41 +00:00
|
|
|
return Api::NewLocalHandle(function);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
cls = cls.SuperClass();
|
|
|
|
}
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("Unable to find field in the class");
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-10-26 20:38:41 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_GetStaticField(Dart_Handle cls,
|
2011-10-05 05:20:07 +00:00
|
|
|
Dart_Handle name) {
|
2011-11-12 05:55:22 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
2011-10-26 20:38:41 +00:00
|
|
|
Dart_Handle result = LookupStaticField(cls, name, kGetter);
|
2011-11-11 19:31:04 +00:00
|
|
|
if (::Dart_IsError(result)) {
|
2011-10-19 19:13:55 +00:00
|
|
|
return result;
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
Object& retval = Object::Handle();
|
2011-10-26 20:38:41 +00:00
|
|
|
const Object& obj = Object::Handle(Api::UnwrapHandle(result));
|
2011-10-05 05:20:07 +00:00
|
|
|
if (obj.IsField()) {
|
|
|
|
Field& fld = Field::Handle();
|
|
|
|
fld ^= obj.raw();
|
|
|
|
retval = fld.value();
|
2011-10-26 20:38:41 +00:00
|
|
|
return Api::NewLocalHandle(retval);
|
2011-10-05 05:20:07 +00:00
|
|
|
} else {
|
|
|
|
Function& func = Function::Handle();
|
|
|
|
func ^= obj.raw();
|
|
|
|
GrowableArray<const Object*> args;
|
2012-02-01 23:39:28 +00:00
|
|
|
InvokeStatic(isolate, func, args, &result);
|
|
|
|
return result;
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// TODO(iposva): The value parameter should be documented as being an instance.
|
2011-11-11 19:31:04 +00:00
|
|
|
// TODO(turnidge): Is this skipping the setter?
|
2011-10-26 20:38:41 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_SetStaticField(Dart_Handle cls,
|
2011-10-05 05:20:07 +00:00
|
|
|
Dart_Handle name,
|
|
|
|
Dart_Handle value) {
|
2011-11-12 05:55:22 +00:00
|
|
|
DARTSCOPE(Isolate::Current());
|
2011-10-26 20:38:41 +00:00
|
|
|
Dart_Handle result = LookupStaticField(cls, name, kSetter);
|
2011-11-11 19:31:04 +00:00
|
|
|
if (::Dart_IsError(result)) {
|
2011-10-19 19:13:55 +00:00
|
|
|
return result;
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
Field& fld = Field::Handle();
|
2011-10-26 20:38:41 +00:00
|
|
|
fld ^= Api::UnwrapHandle(result);
|
2011-10-05 05:20:07 +00:00
|
|
|
if (fld.is_final()) {
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError(
|
|
|
|
"Specified field is a static final field in the class");
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
const Object& val = Object::Handle(Api::UnwrapHandle(value));
|
|
|
|
Instance& instance = Instance::Handle();
|
|
|
|
instance ^= val.raw();
|
|
|
|
fld.set_value(instance);
|
2011-10-26 20:38:41 +00:00
|
|
|
return Api::NewLocalHandle(val);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-10-26 20:38:41 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_GetInstanceField(Dart_Handle obj,
|
2011-10-05 05:20:07 +00:00
|
|
|
Dart_Handle name) {
|
2011-11-12 05:55:22 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
2011-10-05 05:20:07 +00:00
|
|
|
const Object& param = Object::Handle(Api::UnwrapHandle(obj));
|
|
|
|
if (param.IsNull() || !param.IsInstance()) {
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("Invalid object passed in to access instance field");
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
Instance& object = Instance::Handle();
|
|
|
|
object ^= param.raw();
|
2011-10-26 20:38:41 +00:00
|
|
|
Dart_Handle result = LookupInstanceField(object, name, kGetter);
|
2011-11-11 19:31:04 +00:00
|
|
|
if (::Dart_IsError(result)) {
|
2011-10-19 19:13:55 +00:00
|
|
|
return result;
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
Function& func = Function::Handle();
|
2011-10-26 20:38:41 +00:00
|
|
|
func ^= Api::UnwrapHandle(result);
|
2011-10-05 05:20:07 +00:00
|
|
|
GrowableArray<const Object*> arguments;
|
2012-02-01 23:39:28 +00:00
|
|
|
InvokeDynamic(isolate, object, func, arguments, &result);
|
|
|
|
return result;
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-10-26 20:38:41 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_SetInstanceField(Dart_Handle obj,
|
2011-10-05 05:20:07 +00:00
|
|
|
Dart_Handle name,
|
|
|
|
Dart_Handle value) {
|
2011-11-12 05:55:22 +00:00
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
DARTSCOPE(isolate);
|
2011-10-05 05:20:07 +00:00
|
|
|
const Object& param = Object::Handle(Api::UnwrapHandle(obj));
|
|
|
|
if (param.IsNull() || !param.IsInstance()) {
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("Invalid object passed in to access instance field");
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
Instance& object = Instance::Handle();
|
|
|
|
object ^= param.raw();
|
2011-10-26 20:38:41 +00:00
|
|
|
Dart_Handle result = LookupInstanceField(object, name, kSetter);
|
2011-11-11 19:31:04 +00:00
|
|
|
if (::Dart_IsError(result)) {
|
2011-10-19 19:13:55 +00:00
|
|
|
return result;
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
Function& func = Function::Handle();
|
2011-10-26 20:38:41 +00:00
|
|
|
func ^= Api::UnwrapHandle(result);
|
2011-10-05 05:20:07 +00:00
|
|
|
GrowableArray<const Object*> arguments(1);
|
|
|
|
const Object& arg = Object::Handle(Api::UnwrapHandle(value));
|
|
|
|
arguments.Add(&arg);
|
2012-02-01 23:39:28 +00:00
|
|
|
InvokeDynamic(isolate, object, func, arguments, &result);
|
|
|
|
return result;
|
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);
|
2011-10-05 05:20:07 +00:00
|
|
|
const Object& param = Object::Handle(Api::UnwrapHandle(name));
|
|
|
|
if (param.IsNull() || !param.IsString() || field_count <= 0) {
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError(
|
2011-10-26 20:38:41 +00:00
|
|
|
"Invalid arguments passed to Dart_CreateNativeWrapperClass");
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
String& cls_name = String::Handle();
|
|
|
|
cls_name ^= param.raw();
|
|
|
|
cls_name = String::NewSymbol(cls_name);
|
|
|
|
Library& lib = Library::Handle();
|
|
|
|
lib ^= Api::UnwrapHandle(library);
|
|
|
|
if (lib.IsNull()) {
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError(
|
2011-10-26 20:38:41 +00:00
|
|
|
"Invalid arguments passed to Dart_CreateNativeWrapperClass");
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
const Class& cls = Class::Handle(Class::NewNativeWrapper(&lib,
|
|
|
|
cls_name,
|
|
|
|
field_count));
|
|
|
|
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
|
|
|
}
|
2011-10-26 20:38:41 +00:00
|
|
|
return Api::NewLocalHandle(cls);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-10-26 20:38:41 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_GetNativeInstanceField(Dart_Handle obj,
|
|
|
|
int index,
|
|
|
|
intptr_t* value) {
|
2011-11-12 05:55:22 +00:00
|
|
|
DARTSCOPE(Isolate::Current());
|
2011-10-05 05:20:07 +00:00
|
|
|
const Object& param = Object::Handle(Api::UnwrapHandle(obj));
|
|
|
|
if (param.IsNull() || !param.IsInstance()) {
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError(
|
2011-10-26 20:38:41 +00:00
|
|
|
"Invalid object passed in to access native instance field");
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
Instance& object = Instance::Handle();
|
|
|
|
object ^= param.raw();
|
|
|
|
if (!object.IsValidNativeIndex(index)) {
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError(
|
2011-10-26 20:38:41 +00:00
|
|
|
"Invalid index passed in to access native instance field");
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
2011-10-26 20:38:41 +00:00
|
|
|
*value = object.GetNativeField(index);
|
|
|
|
return Api::Success();
|
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) {
|
2011-11-12 05:55:22 +00:00
|
|
|
DARTSCOPE(Isolate::Current());
|
2011-10-05 05:20:07 +00:00
|
|
|
const Object& param = Object::Handle(Api::UnwrapHandle(obj));
|
|
|
|
if (param.IsNull() || !param.IsInstance()) {
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError(
|
|
|
|
"Invalid object passed in to set native instance field");
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
Instance& object = Instance::Handle();
|
|
|
|
object ^= param.raw();
|
|
|
|
if (!object.IsValidNativeIndex(index)) {
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError(
|
|
|
|
"Invalid index passed in to set native instance field");
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
object.SetNativeField(index, value);
|
2011-10-26 20:38:41 +00:00
|
|
|
return Api::Success();
|
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();
|
|
|
|
DARTSCOPE(isolate);
|
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
|
|
|
const Instance& excp = Instance::CheckedHandle(Api::UnwrapHandle(exception));
|
|
|
|
// Unwind all the API scopes till the exit frame before throwing an
|
|
|
|
// exception.
|
|
|
|
ApiState* state = isolate->api_state();
|
|
|
|
ASSERT(state != NULL);
|
|
|
|
state->UnwindScopes(isolate->top_exit_frame_info());
|
|
|
|
Exceptions::Throw(excp);
|
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);
|
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
|
|
|
}
|
|
|
|
DARTSCOPE(isolate);
|
|
|
|
const Instance& excp = Instance::CheckedHandle(Api::UnwrapHandle(exception));
|
|
|
|
const Instance& stk = Instance::CheckedHandle(Api::UnwrapHandle(stacktrace));
|
|
|
|
// Unwind all the API scopes till the exit frame before throwing an
|
|
|
|
// exception.
|
|
|
|
ApiState* state = isolate->api_state();
|
|
|
|
ASSERT(state != NULL);
|
|
|
|
state->UnwindScopes(isolate->top_exit_frame_info());
|
|
|
|
Exceptions::ReThrow(excp, stk);
|
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) {
|
|
|
|
DARTSCOPE(Isolate::Current());
|
|
|
|
NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
|
|
|
|
const Object& obj = Object::Handle(arguments->At(index));
|
|
|
|
return Api::NewLocalHandle(obj);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
DART_EXPORT int Dart_GetNativeArgumentCount(Dart_NativeArguments args) {
|
2011-12-01 19:17:10 +00:00
|
|
|
CHECK_ISOLATE(Isolate::Current());
|
2011-11-22 19:42:38 +00:00
|
|
|
NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
|
|
|
|
return arguments->Count();
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
DART_EXPORT void Dart_SetReturnValue(Dart_NativeArguments args,
|
|
|
|
Dart_Handle retval) {
|
|
|
|
DARTSCOPE(Isolate::Current());
|
|
|
|
NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
|
|
|
|
arguments->SetReturn(Object::Handle(Api::UnwrapHandle(retval)));
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
// --- Scripts and Libraries ---
|
|
|
|
|
|
|
|
|
|
|
|
// 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) {
|
|
|
|
bool update_lib_status = (kind == RawScript::kScript ||
|
|
|
|
kind == RawScript::kLibrary);
|
|
|
|
if (update_lib_status) {
|
|
|
|
lib.SetLoadInProgress();
|
|
|
|
}
|
|
|
|
const Script& script = Script::Handle(Script::New(url, source, kind));
|
|
|
|
ASSERT(isolate != NULL);
|
2012-02-01 23:39:28 +00:00
|
|
|
LongJump* base = isolate->long_jump_base();
|
|
|
|
LongJump jump;
|
|
|
|
isolate->set_long_jump_base(&jump);
|
|
|
|
if (setjmp(*jump.Set()) == 0) {
|
|
|
|
Compiler::Compile(lib, script);
|
2011-11-22 19:42:38 +00:00
|
|
|
*result = Api::NewLocalHandle(lib);
|
|
|
|
if (update_lib_status) {
|
|
|
|
lib.SetLoaded();
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
} else {
|
2012-02-01 23:39:28 +00:00
|
|
|
SetupErrorResult(result);
|
2011-11-22 19:42:38 +00:00
|
|
|
if (update_lib_status) {
|
|
|
|
lib.SetLoadError();
|
|
|
|
}
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
2012-02-01 23:39:28 +00:00
|
|
|
isolate->set_long_jump_base(base);
|
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,
|
|
|
|
Dart_Handle source,
|
|
|
|
Dart_LibraryTagHandler handler) {
|
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);
|
|
|
|
const String& url_str = Api::UnwrapStringHandle(url);
|
|
|
|
if (url_str.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(url, String);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
2011-11-22 19:42:38 +00:00
|
|
|
const String& source_str = Api::UnwrapStringHandle(source);
|
|
|
|
if (source_str.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(source, String);
|
|
|
|
}
|
|
|
|
Library& library = Library::Handle(isolate->object_store()->root_library());
|
|
|
|
if (!library.IsNull()) {
|
|
|
|
const String& library_url = String::Handle(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
|
|
|
}
|
|
|
|
isolate->set_library_tag_handler(handler);
|
|
|
|
library = Library::New(url_str);
|
|
|
|
library.Register();
|
|
|
|
isolate->object_store()->set_root_library(library);
|
|
|
|
Dart_Handle result;
|
|
|
|
CompileSource(isolate,
|
|
|
|
library,
|
|
|
|
url_str,
|
|
|
|
source_str,
|
|
|
|
RawScript::kScript,
|
|
|
|
&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-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("%s expects argument 'buffer' to be non-null.",
|
|
|
|
CURRENT_FUNC);
|
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"
|
|
|
|
" snapshot", CURRENT_FUNC);
|
2011-12-06 00:34:49 +00:00
|
|
|
}
|
|
|
|
Library& library = Library::Handle(isolate->object_store()->root_library());
|
|
|
|
if (!library.IsNull()) {
|
|
|
|
const String& library_url = String::Handle(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-01-10 18:47:38 +00:00
|
|
|
SnapshotReader reader(snapshot, isolate);
|
2011-12-06 00:34:49 +00:00
|
|
|
const Object& tmp = Object::Handle(reader.ReadObject());
|
|
|
|
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();
|
|
|
|
isolate->object_store()->set_root_library(library);
|
|
|
|
return Api::NewLocalHandle(library);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
static void CompileAll(Isolate* isolate, Dart_Handle* result) {
|
2012-02-01 23:39:28 +00:00
|
|
|
*result = Api::Success();
|
2012-01-05 22:33:37 +00:00
|
|
|
ASSERT(isolate != NULL);
|
2012-02-01 23:39:28 +00:00
|
|
|
LongJump* base = isolate->long_jump_base();
|
|
|
|
LongJump jump;
|
|
|
|
isolate->set_long_jump_base(&jump);
|
|
|
|
if (setjmp(*jump.Set()) == 0) {
|
|
|
|
Library::CompileAll();
|
2012-01-05 22:33:37 +00:00
|
|
|
} else {
|
2012-02-01 23:39:28 +00:00
|
|
|
SetupErrorResult(result);
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
2012-02-01 23:39:28 +00:00
|
|
|
isolate->set_long_jump_base(base);
|
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-01-10 21:42:21 +00:00
|
|
|
return Api::NewError(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) {
|
|
|
|
DARTSCOPE(Isolate::Current());
|
|
|
|
const Object& obj = Object::Handle(Api::UnwrapHandle(object));
|
|
|
|
return obj.IsLibrary();
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_GetClass(Dart_Handle library, Dart_Handle name) {
|
|
|
|
DARTSCOPE(Isolate::Current());
|
|
|
|
const Object& param = Object::Handle(Api::UnwrapHandle(name));
|
|
|
|
if (param.IsNull() || !param.IsString()) {
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("Invalid class name specified");
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
|
|
|
const Library& lib = Library::CheckedHandle(Api::UnwrapHandle(library));
|
|
|
|
if (lib.IsNull()) {
|
2012-01-10 21:42:21 +00:00
|
|
|
return Api::NewError("Invalid parameter, Unknown library specified");
|
2011-11-22 19:42:38 +00:00
|
|
|
}
|
|
|
|
String& cls_name = String::Handle();
|
|
|
|
cls_name ^= param.raw();
|
|
|
|
const Class& cls = Class::Handle(lib.LookupClass(cls_name));
|
|
|
|
if (cls.IsNull()) {
|
|
|
|
const String& lib_name = String::Handle(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
|
|
|
}
|
|
|
|
return Api::NewLocalHandle(cls);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_LibraryUrl(Dart_Handle library) {
|
|
|
|
DARTSCOPE(Isolate::Current());
|
|
|
|
const Library& lib = Api::UnwrapLibraryHandle(library);
|
|
|
|
if (lib.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(library, Library);
|
|
|
|
}
|
|
|
|
const String& url = String::Handle(lib.url());
|
|
|
|
ASSERT(!url.IsNull());
|
|
|
|
return Api::NewLocalHandle(url);
|
2011-10-26 20:38:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_LookupLibrary(Dart_Handle url) {
|
2011-11-12 05:55:22 +00:00
|
|
|
DARTSCOPE(Isolate::Current());
|
2011-11-22 19:42:38 +00:00
|
|
|
const String& url_str = Api::UnwrapStringHandle(url);
|
|
|
|
if (url_str.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(url, String);
|
|
|
|
}
|
|
|
|
const Library& library = Library::Handle(Library::LookupLibrary(url_str));
|
|
|
|
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 {
|
|
|
|
return Api::NewLocalHandle(library);
|
|
|
|
}
|
|
|
|
}
|
2011-11-08 00:12:59 +00:00
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_LoadLibrary(Dart_Handle url, 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);
|
|
|
|
const String& url_str = Api::UnwrapStringHandle(url);
|
|
|
|
if (url_str.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(url, String);
|
|
|
|
}
|
|
|
|
const String& source_str = Api::UnwrapStringHandle(source);
|
|
|
|
if (source_str.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(source, String);
|
|
|
|
}
|
|
|
|
Library& library = Library::Handle(Library::LookupLibrary(url_str));
|
|
|
|
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,
|
|
|
|
RawScript::kLibrary,
|
|
|
|
&result);
|
|
|
|
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,
|
|
|
|
Dart_Handle import) {
|
2011-11-12 05:55:22 +00:00
|
|
|
DARTSCOPE(Isolate::Current());
|
2011-11-22 19:42:38 +00:00
|
|
|
const Library& library_vm = Api::UnwrapLibraryHandle(library);
|
|
|
|
if (library_vm.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(library, Library);
|
2011-11-11 19:31:04 +00:00
|
|
|
}
|
2011-11-22 19:42:38 +00:00
|
|
|
const Library& import_vm = Api::UnwrapLibraryHandle(import);
|
|
|
|
if (import_vm.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(import, Library);
|
|
|
|
}
|
|
|
|
library_vm.AddImport(import_vm);
|
|
|
|
return Api::Success();
|
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);
|
|
|
|
const Library& lib = Api::UnwrapLibraryHandle(library);
|
|
|
|
if (lib.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(library, Library);
|
|
|
|
}
|
|
|
|
const String& url_str = Api::UnwrapStringHandle(url);
|
|
|
|
if (url_str.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(url, String);
|
|
|
|
}
|
|
|
|
const String& source_str = Api::UnwrapStringHandle(source);
|
|
|
|
if (source_str.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(source, String);
|
|
|
|
}
|
|
|
|
Dart_Handle result;
|
|
|
|
CompileSource(isolate, lib, url_str, source_str, RawScript::kSource, &result);
|
|
|
|
return result;
|
2011-11-05 00:09:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-22 19:42:38 +00:00
|
|
|
DART_EXPORT Dart_Handle Dart_SetNativeResolver(
|
|
|
|
Dart_Handle library,
|
|
|
|
Dart_NativeEntryResolver resolver) {
|
|
|
|
DARTSCOPE(Isolate::Current());
|
|
|
|
const Library& lib = Api::UnwrapLibraryHandle(library);
|
|
|
|
if (lib.IsNull()) {
|
|
|
|
RETURN_TYPE_ERROR(library, Library);
|
|
|
|
}
|
|
|
|
lib.set_native_entry_resolver(resolver);
|
|
|
|
return Api::Success();
|
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) {
|
|
|
|
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) {
|
|
|
|
*buffer = reinterpret_cast<void*>(Api::Allocate(*buffer_size));
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} // namespace dart
|