mirror of
https://github.com/dart-lang/sdk
synced 2024-11-05 18:22:09 +00:00
Add support for lists and backward references when decoding a message to a Dart_CObject object
The C message reader can now read lists created like this: new List() new List<int>() new List<String>() new List<double>() new List<bool>() The backward references are now resolved and already allocated Dart_CObject objects are reused when there is a backward reference. The reuse of the Dart_CObject objects poses the issue of which objects where allocated with the supplied allocator and which where not. Currently this will work best with a zone allocator. This will be added to the tests in a subsequent change. R=asiva@google.com, turnidge@google.com BUG= TEST= Review URL: https://chromiumcodereview.appspot.com//9303031 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@3831 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
parent
42b70dcddb
commit
3f035ecad0
5 changed files with 383 additions and 61 deletions
|
@ -1416,12 +1416,13 @@ DART_EXPORT void Dart_GetPprofSymbolInfo(void** buffer, int* buffer_size);
|
|||
*/
|
||||
struct Dart_CObject {
|
||||
enum Type {
|
||||
kNull,
|
||||
kNull = 0,
|
||||
kBool,
|
||||
kInt32,
|
||||
kDouble,
|
||||
kString,
|
||||
kArray
|
||||
kArray,
|
||||
kNumberOfTypes
|
||||
};
|
||||
Type type;
|
||||
union {
|
||||
|
|
|
@ -62,6 +62,9 @@ class DynamicAssertionHelper {
|
|||
|
||||
template<typename E, typename A>
|
||||
void GreaterEqual(const E& left, const A& right);
|
||||
|
||||
template<typename T>
|
||||
void NotNull(const T p);
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
@ -196,6 +199,13 @@ void DynamicAssertionHelper::GreaterEqual(const E& left, const A& right) {
|
|||
std::string es = ess.str(), as = ass.str();
|
||||
Fail("expected: %s >= %s", es.c_str(), as.c_str());
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
void DynamicAssertionHelper::NotNull(const T p) {
|
||||
if (p != NULL) return;
|
||||
Fail("expected: not NULL, found NULL");
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace dart
|
||||
|
@ -277,6 +287,9 @@ void DynamicAssertionHelper::GreaterEqual(const E& left, const A& right) {
|
|||
|
||||
#define EXPECT_GE(left, right) \
|
||||
dart::Expect(__FILE__, __LINE__).GreaterEqual((left), (right))
|
||||
|
||||
#define EXPECT_NOTNULL(ptr) \
|
||||
dart::Expect(__FILE__, __LINE__).NotNull((ptr))
|
||||
#endif
|
||||
|
||||
// TODO(iposva): provide a better way to get extra info on an EXPECT
|
||||
|
|
|
@ -440,7 +440,18 @@ RawObject* SnapshotReader::ReadInlinedObject(intptr_t object_id) {
|
|||
CMessageReader::CMessageReader(const uint8_t* buffer,
|
||||
intptr_t length,
|
||||
ReAlloc alloc)
|
||||
: BaseReader(buffer, length), alloc_(alloc) {
|
||||
: BaseReader(buffer, length),
|
||||
alloc_(alloc),
|
||||
backward_references_(kNumInitialReferences) {
|
||||
// Initialize marker objects used to handle Lists.
|
||||
// TODO(sjesse): Remove this when message serialization format is
|
||||
// updated.
|
||||
memset(&type_arguments_marker, 0, sizeof(type_arguments_marker));
|
||||
memset(&dynamic_type_marker, 0, sizeof(dynamic_type_marker));
|
||||
type_arguments_marker.type =
|
||||
static_cast<Dart_CObject::Type>(Dart_CObject_Internal::kTypeArguments);
|
||||
dynamic_type_marker.type =
|
||||
static_cast<Dart_CObject::Type>(Dart_CObject_Internal::kDynamicType);
|
||||
}
|
||||
|
||||
|
||||
|
@ -452,7 +463,7 @@ intptr_t CMessageReader::LookupInternalClass(intptr_t class_header) {
|
|||
}
|
||||
|
||||
|
||||
Dart_CObject* CMessageReader::AllocateDartValue(Dart_CObject::Type type) {
|
||||
Dart_CObject* CMessageReader::AllocateDartCObject(Dart_CObject::Type type) {
|
||||
Dart_CObject* value =
|
||||
reinterpret_cast<Dart_CObject*>(
|
||||
alloc_(NULL, 0, sizeof(Dart_CObject)));
|
||||
|
@ -461,33 +472,33 @@ Dart_CObject* CMessageReader::AllocateDartValue(Dart_CObject::Type type) {
|
|||
}
|
||||
|
||||
|
||||
Dart_CObject* CMessageReader::AllocateDartValueNull() {
|
||||
return AllocateDartValue(Dart_CObject::kNull);
|
||||
Dart_CObject* CMessageReader::AllocateDartCObjectNull() {
|
||||
return AllocateDartCObject(Dart_CObject::kNull);
|
||||
}
|
||||
|
||||
|
||||
Dart_CObject* CMessageReader::AllocateDartValueBool(bool val) {
|
||||
Dart_CObject* value = AllocateDartValue(Dart_CObject::kBool);
|
||||
Dart_CObject* CMessageReader::AllocateDartCObjectBool(bool val) {
|
||||
Dart_CObject* value = AllocateDartCObject(Dart_CObject::kBool);
|
||||
value->value.as_bool = val;
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
Dart_CObject* CMessageReader::AllocateDartValueInt32(int32_t val) {
|
||||
Dart_CObject* value = AllocateDartValue(Dart_CObject::kInt32);
|
||||
Dart_CObject* CMessageReader::AllocateDartCObjectInt32(int32_t val) {
|
||||
Dart_CObject* value = AllocateDartCObject(Dart_CObject::kInt32);
|
||||
value->value.as_int32 = val;
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
Dart_CObject* CMessageReader::AllocateDartValueDouble(double val) {
|
||||
Dart_CObject* value = AllocateDartValue(Dart_CObject::kDouble);
|
||||
Dart_CObject* CMessageReader::AllocateDartCObjectDouble(double val) {
|
||||
Dart_CObject* value = AllocateDartCObject(Dart_CObject::kDouble);
|
||||
value->value.as_double = val;
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
Dart_CObject* CMessageReader::AllocateDartValueString(intptr_t length) {
|
||||
Dart_CObject* CMessageReader::AllocateDartCObjectString(intptr_t length) {
|
||||
// Allocate a Dart_CObject structure followed by an array of chars
|
||||
// for the string content. The pointer to the string content is set
|
||||
// up to this area.
|
||||
|
@ -500,7 +511,7 @@ Dart_CObject* CMessageReader::AllocateDartValueString(intptr_t length) {
|
|||
}
|
||||
|
||||
|
||||
Dart_CObject* CMessageReader::AllocateDartValueArray(intptr_t length) {
|
||||
Dart_CObject* CMessageReader::AllocateDartCObjectArray(intptr_t length) {
|
||||
// Allocate a Dart_CObject structure followed by an array of
|
||||
// pointers to Dart_CObject structures. The pointer to the array
|
||||
// content is set up to this area.
|
||||
|
@ -536,15 +547,31 @@ Dart_CObject* CMessageReader::ReadInlinedObject(intptr_t object_id) {
|
|||
case Object::kClassClass: {
|
||||
return NULL;
|
||||
}
|
||||
case Object::kTypeArgumentsClass: {
|
||||
// TODO(sjesse): Remove this when message serialization format is
|
||||
// updated (currently length is leaked).
|
||||
AddBackwardReference(object_id, NULL);
|
||||
Dart_CObject* length = ReadObject();
|
||||
ASSERT(length->type == Dart_CObject::kInt32);
|
||||
for (int i = 0; i < length->value.as_int32; i++) {
|
||||
Dart_CObject* type = ReadObject();
|
||||
if (type != &dynamic_type_marker) return NULL;
|
||||
}
|
||||
return &type_arguments_marker;
|
||||
break;
|
||||
}
|
||||
case ObjectStore::kArrayClass: {
|
||||
intptr_t len = ReadSmiValue();
|
||||
Dart_CObject* value = AllocateDartCObjectArray(len);
|
||||
AddBackwardReference(object_id, value);
|
||||
// Skip type arguments.
|
||||
// TODO(sjesse): Remove this when message serialization format is
|
||||
// updated (currently type_arguments is leaked).
|
||||
Dart_CObject* type_arguments = ReadObject();
|
||||
if (type_arguments == NULL ||
|
||||
if (type_arguments != &type_arguments_marker &&
|
||||
type_arguments->type != Dart_CObject::kNull) {
|
||||
return NULL;
|
||||
}
|
||||
Dart_CObject* value = AllocateDartValueArray(len);
|
||||
for (int i = 0; i < len; i++) {
|
||||
value->value.as_array.values[i] = ReadObject();
|
||||
}
|
||||
|
@ -553,21 +580,24 @@ Dart_CObject* CMessageReader::ReadInlinedObject(intptr_t object_id) {
|
|||
}
|
||||
case ObjectStore::kDoubleClass: {
|
||||
// Read the double value for the object.
|
||||
return AllocateDartValueDouble(Read<double>());
|
||||
Dart_CObject* object = AllocateDartCObjectDouble(Read<double>());
|
||||
AddBackwardReference(object_id, object);
|
||||
return object;
|
||||
break;
|
||||
}
|
||||
case ObjectStore::kOneByteStringClass: {
|
||||
intptr_t len = ReadSmiValue();
|
||||
intptr_t hash = ReadSmiValue();
|
||||
USE(hash);
|
||||
Dart_CObject* value = AllocateDartValueString(len);
|
||||
char* p = value->value.as_string;
|
||||
Dart_CObject* object = AllocateDartCObjectString(len);
|
||||
AddBackwardReference(object_id, object);
|
||||
char* p = object->value.as_string;
|
||||
for (intptr_t i = 0; i < len; i++) {
|
||||
*p = Read<uint8_t>();
|
||||
p++;
|
||||
}
|
||||
*p = '\0';
|
||||
return value;
|
||||
return object;
|
||||
break;
|
||||
}
|
||||
case ObjectStore::kTwoByteStringClass:
|
||||
|
@ -587,14 +617,23 @@ Dart_CObject* CMessageReader::ReadInlinedObject(intptr_t object_id) {
|
|||
|
||||
Dart_CObject* CMessageReader::ReadIndexedObject(intptr_t object_id) {
|
||||
if (object_id == Object::kNullObject) {
|
||||
return AllocateDartValueNull();
|
||||
return AllocateDartCObjectNull();
|
||||
} else if (object_id == ObjectStore::kTrueValue) {
|
||||
return AllocateDartValueBool(true);
|
||||
return AllocateDartCObjectBool(true);
|
||||
} else if (object_id == ObjectStore::kFalseValue) {
|
||||
return AllocateDartValueBool(false);
|
||||
return AllocateDartCObjectBool(false);
|
||||
} else if (object_id == ObjectStore::kDynamicType ||
|
||||
object_id == ObjectStore::kDoubleInterface ||
|
||||
object_id == ObjectStore::kIntInterface ||
|
||||
object_id == ObjectStore::kBoolInterface ||
|
||||
object_id == ObjectStore::kStringInterface) {
|
||||
// Always return dynamic type (this is only a marker).
|
||||
return &dynamic_type_marker;
|
||||
} else {
|
||||
// TODO(sgjesse): Handle back-references.
|
||||
UNREACHABLE();
|
||||
intptr_t index = object_id - kMaxPredefinedObjectIds;
|
||||
ASSERT(index < backward_references_.length());
|
||||
ASSERT(backward_references_[index] != NULL);
|
||||
return backward_references_[index];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
@ -615,7 +654,7 @@ Dart_CObject* CMessageReader::ReadObjectImpl(intptr_t header) {
|
|||
Dart_CObject* CMessageReader::ReadObject() {
|
||||
int64_t value = Read<int64_t>();
|
||||
if ((value & kSmiTagMask) == 0) {
|
||||
Dart_CObject* dart_value = AllocateDartValueInt32(value >> kSmiTagShift);
|
||||
Dart_CObject* dart_value = AllocateDartCObjectInt32(value >> kSmiTagShift);
|
||||
return dart_value;
|
||||
}
|
||||
ASSERT((value <= kIntptrMax) && (value >= kIntptrMin));
|
||||
|
@ -623,6 +662,12 @@ Dart_CObject* CMessageReader::ReadObject() {
|
|||
}
|
||||
|
||||
|
||||
void CMessageReader::AddBackwardReference(intptr_t id, Dart_CObject* obj) {
|
||||
ASSERT((id - kMaxPredefinedObjectIds) == backward_references_.length());
|
||||
backward_references_.Add(obj);
|
||||
}
|
||||
|
||||
|
||||
void MessageWriter::WriteMessage(intptr_t field_count, intptr_t *data) {
|
||||
// Write out the serialization header value for this object.
|
||||
WriteSerializationMarker(kInlined, kMaxPredefinedObjectIds);
|
||||
|
|
|
@ -404,6 +404,20 @@ class SnapshotReader : public BaseReader {
|
|||
};
|
||||
|
||||
|
||||
// Use this C structure for reading internal objects in the serialized
|
||||
// data. These are objects that we need to process in order to
|
||||
// generate the Dart_CObject graph but that we don't want to expose in
|
||||
// that graph.
|
||||
// TODO(sjesse): Remove this when message serialization format is
|
||||
// updated.
|
||||
struct Dart_CObject_Internal : public Dart_CObject {
|
||||
enum Type {
|
||||
kTypeArguments = Dart_CObject::kNumberOfTypes,
|
||||
kDynamicType,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
// Reads a message snapshot into C structure.
|
||||
class CMessageReader : public BaseReader {
|
||||
public:
|
||||
|
@ -414,28 +428,40 @@ class CMessageReader : public BaseReader {
|
|||
|
||||
private:
|
||||
// Allocates a Dart_CObject object on the C heap.
|
||||
Dart_CObject* AllocateDartValue();
|
||||
Dart_CObject* AllocateDartCObject();
|
||||
// Allocates a Dart_CObject object with the specified type on the C heap.
|
||||
Dart_CObject* AllocateDartValue(Dart_CObject::Type type);
|
||||
Dart_CObject* AllocateDartCObject(Dart_CObject::Type type);
|
||||
// Allocates a Dart_CObject object for the null object on the C heap.
|
||||
Dart_CObject* AllocateDartValueNull();
|
||||
Dart_CObject* AllocateDartCObjectNull();
|
||||
// Allocates a Dart_CObject object for a boolean object on the C heap.
|
||||
Dart_CObject* AllocateDartValueBool(bool value);
|
||||
Dart_CObject* AllocateDartCObjectBool(bool value);
|
||||
// Allocates a Dart_CObject object for for a 32-bit integer on the C heap.
|
||||
Dart_CObject* AllocateDartValueInt32(int32_t value);
|
||||
Dart_CObject* AllocateDartCObjectInt32(int32_t value);
|
||||
// Allocates a Dart_CObject object for a double on the C heap.
|
||||
Dart_CObject* AllocateDartValueDouble(double value);
|
||||
Dart_CObject* AllocateDartCObjectDouble(double value);
|
||||
// Allocates a Dart_CObject object for string data on the C heap.
|
||||
Dart_CObject* AllocateDartValueString(intptr_t length);
|
||||
Dart_CObject* AllocateDartCObjectString(intptr_t length);
|
||||
// Allocates a C array of Dart_CObject objects on the C heap.
|
||||
Dart_CObject* AllocateDartValueArray(intptr_t length);
|
||||
Dart_CObject* AllocateDartCObjectArray(intptr_t length);
|
||||
|
||||
intptr_t LookupInternalClass(intptr_t class_header);
|
||||
Dart_CObject* ReadInlinedObject(intptr_t object_id);
|
||||
Dart_CObject* ReadObjectImpl(intptr_t header);
|
||||
Dart_CObject* ReadIndexedObject(intptr_t object_id);
|
||||
|
||||
// Add object to backward references.
|
||||
void AddBackwardReference(intptr_t id, Dart_CObject* obj);
|
||||
|
||||
Dart_CObject_Internal* AsInternal(Dart_CObject* object) {
|
||||
ASSERT(object->type >= Dart_CObject::kNumberOfTypes);
|
||||
return reinterpret_cast<Dart_CObject_Internal*>(object);
|
||||
}
|
||||
|
||||
ReAlloc alloc_;
|
||||
GrowableArray<Dart_CObject*> backward_references_;
|
||||
|
||||
Dart_CObject type_arguments_marker;
|
||||
Dart_CObject dynamic_type_marker;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -64,6 +64,7 @@ TEST_CASE(SerializeNull) {
|
|||
writer.BytesWritten(),
|
||||
&allocator);
|
||||
Dart_CObject* cobject = mreader.ReadObject();
|
||||
EXPECT_NOTNULL(cobject);
|
||||
EXPECT_EQ(Dart_CObject::kNull, cobject->type);
|
||||
free(cobject);
|
||||
}
|
||||
|
@ -90,6 +91,7 @@ TEST_CASE(SerializeSmi1) {
|
|||
writer.BytesWritten(),
|
||||
&allocator);
|
||||
Dart_CObject* cobject = mreader.ReadObject();
|
||||
EXPECT_NOTNULL(cobject);
|
||||
EXPECT_EQ(Dart_CObject::kInt32, cobject->type);
|
||||
EXPECT_EQ(smi.Value(), cobject->value.as_int32);
|
||||
free(cobject);
|
||||
|
@ -117,6 +119,7 @@ TEST_CASE(SerializeSmi2) {
|
|||
writer.BytesWritten(),
|
||||
&allocator);
|
||||
Dart_CObject* cobject = mreader.ReadObject();
|
||||
EXPECT_NOTNULL(cobject);
|
||||
EXPECT_EQ(Dart_CObject::kInt32, cobject->type);
|
||||
EXPECT_EQ(smi.Value(), cobject->value.as_int32);
|
||||
free(cobject);
|
||||
|
@ -144,6 +147,7 @@ TEST_CASE(SerializeDouble) {
|
|||
writer.BytesWritten(),
|
||||
&allocator);
|
||||
Dart_CObject* cobject = mreader.ReadObject();
|
||||
EXPECT_NOTNULL(cobject);
|
||||
EXPECT_EQ(Dart_CObject::kDouble, cobject->type);
|
||||
EXPECT_EQ(dbl.value(), cobject->value.as_double);
|
||||
free(cobject);
|
||||
|
@ -173,9 +177,11 @@ TEST_CASE(SerializeBool) {
|
|||
writer.BytesWritten(),
|
||||
&allocator);
|
||||
Dart_CObject* cobject1 = mreader.ReadObject();
|
||||
EXPECT_NOTNULL(cobject1);
|
||||
EXPECT_EQ(Dart_CObject::kBool, cobject1->type);
|
||||
EXPECT_EQ(true, cobject1->value.as_bool);
|
||||
Dart_CObject* cobject2 = mreader.ReadObject();
|
||||
EXPECT_NOTNULL(cobject2);
|
||||
EXPECT_EQ(Dart_CObject::kBool, cobject2->type);
|
||||
EXPECT_EQ(false, cobject2->value.as_bool);
|
||||
free(cobject1);
|
||||
|
@ -693,18 +699,46 @@ TEST_CASE(IntArrayMessage) {
|
|||
}
|
||||
|
||||
|
||||
// Helper function to call a top level Dart function, serialize the
|
||||
// result and deserialize the result into a Dart_CObject structure.
|
||||
static Dart_CObject* GetDeserializedDartObject(Dart_Handle lib,
|
||||
const char* dart_function) {
|
||||
Dart_Handle result;
|
||||
result = Dart_InvokeStatic(lib,
|
||||
Dart_NewString(""),
|
||||
Dart_NewString(dart_function),
|
||||
0,
|
||||
NULL);
|
||||
EXPECT_VALID(result);
|
||||
|
||||
// Serialize the list into a message.
|
||||
uint8_t* buffer;
|
||||
SnapshotWriter writer(Snapshot::kMessage, &buffer, &allocator);
|
||||
const Object& list = Object::Handle(Api::UnwrapHandle(result));
|
||||
writer.WriteObject(list.raw());
|
||||
writer.FinalizeBuffer();
|
||||
|
||||
// Read object back from the snapshot into a C structure.
|
||||
CMessageReader reader(buffer + Snapshot::kHeaderSize,
|
||||
writer.BytesWritten(),
|
||||
&allocator);
|
||||
Dart_CObject* value = reader.ReadObject();
|
||||
free(buffer);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
UNIT_TEST_CASE(DartGeneratedMessages) {
|
||||
const int kArrayLength = 10;
|
||||
static const char* kCustomIsolateScriptChars =
|
||||
"getSmi() {\n"
|
||||
" return 42;\n"
|
||||
"}\n"
|
||||
"getString() {\n"
|
||||
"getSmi() {\n"
|
||||
" return 42;\n"
|
||||
"}\n"
|
||||
"getString() {\n"
|
||||
" return \"Hello, world!\";\n"
|
||||
"}\n"
|
||||
"getList() {\n"
|
||||
" return [1,2,3,4,5,6,7,8,9,10];\n"
|
||||
"}\n";
|
||||
"}\n"
|
||||
"getList() {\n"
|
||||
" return new List(kArrayLength);\n"
|
||||
"}\n";
|
||||
|
||||
TestCase::CreateTestIsolate();
|
||||
Isolate* isolate = Isolate::Current();
|
||||
|
@ -729,17 +763,7 @@ UNIT_TEST_CASE(DartGeneratedMessages) {
|
|||
NULL);
|
||||
EXPECT_VALID(string_result);
|
||||
EXPECT(Dart_IsString(string_result));
|
||||
Dart_Handle list_result;
|
||||
list_result = Dart_InvokeStatic(lib,
|
||||
Dart_NewString(""),
|
||||
Dart_NewString("getList"),
|
||||
0,
|
||||
NULL);
|
||||
EXPECT_VALID(list_result);
|
||||
EXPECT(Dart_IsList(list_result));
|
||||
intptr_t result_len = 0;
|
||||
EXPECT_VALID(Dart_ListLength(list_result, &result_len));
|
||||
EXPECT_EQ(kArrayLength, result_len);
|
||||
|
||||
{
|
||||
DARTSCOPE_NOCHECKS(isolate);
|
||||
|
||||
|
@ -756,6 +780,7 @@ UNIT_TEST_CASE(DartGeneratedMessages) {
|
|||
writer.BytesWritten(),
|
||||
&allocator);
|
||||
Dart_CObject* value = mreader.ReadObject();
|
||||
EXPECT_NOTNULL(value);
|
||||
EXPECT_EQ(Dart_CObject::kInt32, value->type);
|
||||
EXPECT_EQ(42, value->value.as_int32);
|
||||
free(value);
|
||||
|
@ -774,19 +799,231 @@ UNIT_TEST_CASE(DartGeneratedMessages) {
|
|||
writer.BytesWritten(),
|
||||
&allocator);
|
||||
Dart_CObject* value = mreader.ReadObject();
|
||||
EXPECT_NOTNULL(value);
|
||||
EXPECT_EQ(Dart_CObject::kString, value->type);
|
||||
EXPECT_STREQ("Hello, world!", value->value.as_string);
|
||||
free(value);
|
||||
free(buffer);
|
||||
}
|
||||
}
|
||||
Dart_ExitScope();
|
||||
Dart_ShutdownIsolate();
|
||||
}
|
||||
|
||||
|
||||
UNIT_TEST_CASE(DartGeneratedListMessages) {
|
||||
const int kArrayLength = 10;
|
||||
static const char* kScriptChars =
|
||||
"final int kArrayLength = 10;\n"
|
||||
"getList() {\n"
|
||||
" return new List(kArrayLength);\n"
|
||||
"}\n"
|
||||
"getIntList() {\n"
|
||||
" var list = new List<int>(kArrayLength);\n"
|
||||
" for (var i = 0; i < kArrayLength; i++) list[i] = i;\n"
|
||||
" return list;\n"
|
||||
"}\n"
|
||||
"getStringList() {\n"
|
||||
" var list = new List<String>(kArrayLength);\n"
|
||||
" for (var i = 0; i < kArrayLength; i++) list[i] = i.toString();\n"
|
||||
" return list;\n"
|
||||
"}\n"
|
||||
"getMixedList() {\n"
|
||||
" var list = new List(kArrayLength);\n"
|
||||
" list[0] = 0;\n"
|
||||
" list[1] = '1';\n"
|
||||
" list[2] = 2.2;\n"
|
||||
" list[3] = true;\n"
|
||||
" return list;\n"
|
||||
"}\n";
|
||||
|
||||
TestCase::CreateTestIsolate();
|
||||
Isolate* isolate = Isolate::Current();
|
||||
EXPECT(isolate != NULL);
|
||||
Dart_EnterScope();
|
||||
|
||||
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
|
||||
EXPECT_VALID(lib);
|
||||
|
||||
{
|
||||
DARTSCOPE_NOCHECKS(isolate);
|
||||
|
||||
{
|
||||
uint8_t* buffer;
|
||||
SnapshotWriter writer(Snapshot::kMessage, &buffer, &allocator);
|
||||
const Object& list = Object::Handle(Api::UnwrapHandle(list_result));
|
||||
writer.WriteObject(list.raw());
|
||||
writer.FinalizeBuffer();
|
||||
// TODO(sgjesse): Make this work!
|
||||
free(buffer);
|
||||
// Generate a list of nulls from Dart code.
|
||||
Dart_CObject* value = GetDeserializedDartObject(lib, "getList");
|
||||
EXPECT_NOTNULL(value);
|
||||
EXPECT_EQ(Dart_CObject::kArray, value->type);
|
||||
EXPECT_EQ(kArrayLength, value->value.as_array.length);
|
||||
for (int i = 0; i < kArrayLength; i++) {
|
||||
EXPECT_EQ(Dart_CObject::kNull, value->value.as_array.values[i]->type);
|
||||
free(value->value.as_array.values[i]);
|
||||
}
|
||||
free(value);
|
||||
}
|
||||
{
|
||||
// Generate a list of ints from Dart code.
|
||||
Dart_CObject* value = GetDeserializedDartObject(lib, "getIntList");
|
||||
EXPECT_NOTNULL(value);
|
||||
EXPECT_EQ(Dart_CObject::kArray, value->type);
|
||||
EXPECT_EQ(kArrayLength, value->value.as_array.length);
|
||||
for (int i = 0; i < kArrayLength; i++) {
|
||||
EXPECT_EQ(Dart_CObject::kInt32, value->value.as_array.values[i]->type);
|
||||
EXPECT_EQ(i, value->value.as_array.values[i]->value.as_int32);
|
||||
free(value->value.as_array.values[i]);
|
||||
}
|
||||
free(value);
|
||||
}
|
||||
{
|
||||
// Generate a list of strings from Dart code.
|
||||
Dart_CObject* value = GetDeserializedDartObject(lib, "getStringList");
|
||||
EXPECT_NOTNULL(value);
|
||||
EXPECT_EQ(Dart_CObject::kArray, value->type);
|
||||
EXPECT_EQ(kArrayLength, value->value.as_array.length);
|
||||
for (int i = 0; i < kArrayLength; i++) {
|
||||
EXPECT_EQ(Dart_CObject::kString, value->value.as_array.values[i]->type);
|
||||
char buffer[3];
|
||||
snprintf(buffer, sizeof(buffer), "%d", i);
|
||||
EXPECT_STREQ(buffer, value->value.as_array.values[i]->value.as_string);
|
||||
free(value->value.as_array.values[i]);
|
||||
}
|
||||
free(value);
|
||||
}
|
||||
{
|
||||
// Generate a list of objects of different types from Dart code.
|
||||
Dart_CObject* value = GetDeserializedDartObject(lib, "getMixedList");
|
||||
EXPECT_NOTNULL(value);
|
||||
EXPECT_EQ(Dart_CObject::kArray, value->type);
|
||||
EXPECT_EQ(kArrayLength, value->value.as_array.length);
|
||||
|
||||
EXPECT_EQ(Dart_CObject::kInt32, value->value.as_array.values[0]->type);
|
||||
EXPECT_EQ(0, value->value.as_array.values[0]->value.as_int32);
|
||||
EXPECT_EQ(Dart_CObject::kString, value->value.as_array.values[1]->type);
|
||||
EXPECT_STREQ("1", value->value.as_array.values[1]->value.as_string);
|
||||
EXPECT_EQ(Dart_CObject::kDouble, value->value.as_array.values[2]->type);
|
||||
EXPECT_EQ(2.2, value->value.as_array.values[2]->value.as_double);
|
||||
EXPECT_EQ(Dart_CObject::kBool, value->value.as_array.values[3]->type);
|
||||
EXPECT_EQ(true, value->value.as_array.values[3]->value.as_bool);
|
||||
|
||||
for (int i = 0; i < kArrayLength; i++) {
|
||||
if (i > 3) {
|
||||
EXPECT_EQ(Dart_CObject::kNull, value->value.as_array.values[i]->type);
|
||||
}
|
||||
free(value->value.as_array.values[i]);
|
||||
}
|
||||
free(value);
|
||||
}
|
||||
}
|
||||
Dart_ExitScope();
|
||||
Dart_ShutdownIsolate();
|
||||
}
|
||||
|
||||
|
||||
UNIT_TEST_CASE(DartGeneratedListMessagesWithBackref) {
|
||||
const int kArrayLength = 10;
|
||||
static const char* kScriptChars =
|
||||
"final int kArrayLength = 10;\n"
|
||||
"getStringList() {\n"
|
||||
" var s = 'Hello, world!';\n"
|
||||
" var list = new List<String>(kArrayLength);\n"
|
||||
" for (var i = 0; i < kArrayLength; i++) list[i] = s;\n"
|
||||
" return list;\n"
|
||||
"}\n"
|
||||
"getDoubleList() {\n"
|
||||
" var d = 3.14;\n"
|
||||
" var list = new List<double>(kArrayLength);\n"
|
||||
" for (var i = 0; i < kArrayLength; i++) list[i] = d;\n"
|
||||
" return list;\n"
|
||||
"}\n"
|
||||
"getMixedList() {\n"
|
||||
" var list = new List(kArrayLength);\n"
|
||||
" for (var i = 0; i < kArrayLength; i++) {\n"
|
||||
" list[i] = ((i % 2) == 0) ? 'A' : 2.72;\n"
|
||||
" }\n"
|
||||
" return list;\n"
|
||||
"}\n"
|
||||
"getSelfRefList() {\n"
|
||||
" var list = new List(kArrayLength);\n"
|
||||
" for (var i = 0; i < kArrayLength; i++) {\n"
|
||||
" list[i] = list;\n"
|
||||
" }\n"
|
||||
" return list;\n"
|
||||
"}\n";
|
||||
|
||||
TestCase::CreateTestIsolate();
|
||||
Isolate* isolate = Isolate::Current();
|
||||
EXPECT(isolate != NULL);
|
||||
Dart_EnterScope();
|
||||
|
||||
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
|
||||
EXPECT_VALID(lib);
|
||||
|
||||
{
|
||||
DARTSCOPE_NOCHECKS(isolate);
|
||||
|
||||
{
|
||||
// Generate a list of strings from Dart code.
|
||||
Dart_CObject* object = GetDeserializedDartObject(lib, "getStringList");
|
||||
EXPECT_NOTNULL(object);
|
||||
EXPECT_EQ(Dart_CObject::kArray, object->type);
|
||||
EXPECT_EQ(kArrayLength, object->value.as_array.length);
|
||||
for (int i = 0; i < kArrayLength; i++) {
|
||||
Dart_CObject* element = object->value.as_array.values[i];
|
||||
EXPECT_EQ(object->value.as_array.values[0], element);
|
||||
EXPECT_EQ(Dart_CObject::kString, element->type);
|
||||
EXPECT_STREQ("Hello, world!", element->value.as_string);
|
||||
}
|
||||
free(object->value.as_array.values[0]);
|
||||
free(object);
|
||||
}
|
||||
{
|
||||
// Generate a list of doubles from Dart code.
|
||||
Dart_CObject* object = GetDeserializedDartObject(lib, "getDoubleList");
|
||||
EXPECT_NOTNULL(object);
|
||||
EXPECT_EQ(Dart_CObject::kArray, object->type);
|
||||
EXPECT_EQ(kArrayLength, object->value.as_array.length);
|
||||
for (int i = 0; i < kArrayLength; i++) {
|
||||
Dart_CObject* element = object->value.as_array.values[i];
|
||||
EXPECT_EQ(object->value.as_array.values[0], element);
|
||||
EXPECT_EQ(Dart_CObject::kDouble, element->type);
|
||||
EXPECT_EQ(3.14, element->value.as_double);
|
||||
}
|
||||
free(object->value.as_array.values[0]);
|
||||
free(object);
|
||||
}
|
||||
{
|
||||
// Generate a list of objects of different types from Dart code.
|
||||
Dart_CObject* object = GetDeserializedDartObject(lib, "getMixedList");
|
||||
EXPECT_NOTNULL(object);
|
||||
EXPECT_EQ(Dart_CObject::kArray, object->type);
|
||||
EXPECT_EQ(kArrayLength, object->value.as_array.length);
|
||||
for (int i = 0; i < kArrayLength; i++) {
|
||||
Dart_CObject* element = object->value.as_array.values[i];
|
||||
if ((i % 2) == 0) {
|
||||
EXPECT_EQ(object->value.as_array.values[0], element);
|
||||
EXPECT_EQ(Dart_CObject::kString, element->type);
|
||||
EXPECT_STREQ("A", element->value.as_string);
|
||||
} else {
|
||||
EXPECT_EQ(object->value.as_array.values[1], element);
|
||||
EXPECT_EQ(Dart_CObject::kDouble, element->type);
|
||||
EXPECT_STREQ(2.72, element->value.as_double);
|
||||
}
|
||||
}
|
||||
free(object->value.as_array.values[0]);
|
||||
free(object->value.as_array.values[1]);
|
||||
free(object);
|
||||
}
|
||||
{
|
||||
// Generate a list of objects of different types from Dart code.
|
||||
Dart_CObject* object = GetDeserializedDartObject(lib, "getSelfRefList");
|
||||
EXPECT_NOTNULL(object);
|
||||
EXPECT_EQ(Dart_CObject::kArray, object->type);
|
||||
EXPECT_EQ(kArrayLength, object->value.as_array.length);
|
||||
for (int i = 0; i < kArrayLength; i++) {
|
||||
Dart_CObject* element = object->value.as_array.values[i];
|
||||
EXPECT_EQ(Dart_CObject::kArray, element->type);
|
||||
EXPECT_EQ(object, element);
|
||||
}
|
||||
free(object);
|
||||
}
|
||||
}
|
||||
Dart_ExitScope();
|
||||
|
|
Loading…
Reference in a new issue