mirror of
https://github.com/dart-lang/sdk
synced 2024-09-19 15:01:29 +00:00
Add Dart_Invoke, which will replace Dart_InvokeDynamic and Dart_InvokeStatic.
Fixed Dart_SetField to allow us to set a field to null. Review URL: https://chromiumcodereview.appspot.com//9608024 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@5433 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
parent
cd8cdc5fe8
commit
3d363b570f
|
@ -1655,6 +1655,34 @@ DART_EXPORT void Dart_ClosureSetSmrck(Dart_Handle object, int64_t value);
|
|||
// --- Methods and Fields ---
|
||||
|
||||
/**
|
||||
* Invokes a method or function.
|
||||
*
|
||||
* The 'target' parameter may be an object, class, or library. If
|
||||
* 'target' is an object, then this function will invoke an instance
|
||||
* method. If 'target' is a class, then this function will invoke a
|
||||
* static method. If 'target' is a library, then this function will
|
||||
* invoke a top-level function from that library.
|
||||
*
|
||||
* This function ignores visibility (leading underscores in names).
|
||||
*
|
||||
* May generate an unhandled exception error.
|
||||
*
|
||||
* \param target An object, class, or library.
|
||||
* \param name The name of the function or method to invoke.
|
||||
* \param number_of_arguments Size of the arguments array.
|
||||
* \param arguments An array of arguments to the function.
|
||||
*
|
||||
* \return If the function or method is called and completes
|
||||
* successfully, then the return value is returned. If an error
|
||||
* occurs during execution, then an error handle is returned.
|
||||
*/
|
||||
DART_EXPORT Dart_Handle Dart_Invoke(Dart_Handle target,
|
||||
Dart_Handle name,
|
||||
int number_of_arguments,
|
||||
Dart_Handle* arguments);
|
||||
/**
|
||||
* DEPRECATED: Use Dart_Invoke instead.
|
||||
*
|
||||
* Invokes a static method with the given arguments.
|
||||
*
|
||||
* May generate an unhandled exception error.
|
||||
|
@ -1670,6 +1698,8 @@ DART_EXPORT Dart_Handle Dart_InvokeStatic(Dart_Handle library,
|
|||
Dart_Handle* arguments);
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use Dart_Invoke instead.
|
||||
*
|
||||
* Invokes an instance method with the given arguments.
|
||||
*
|
||||
* May generate an unhandled exception error.
|
||||
|
@ -1686,18 +1716,18 @@ DART_EXPORT Dart_Handle Dart_InvokeDynamic(Dart_Handle receiver,
|
|||
/**
|
||||
* Gets the value of a field.
|
||||
*
|
||||
* The 'container' parameter may actually be an object, class, or
|
||||
* library. If 'container' is an object, then this function will
|
||||
* access an instance field. If 'container' is a class, then this
|
||||
* function will access a static field. If 'container' is a library,
|
||||
* then this function will access a top-level variable.
|
||||
* The 'container' parameter may be an object, class, or library. If
|
||||
* 'container' is an object, then this function will access an
|
||||
* instance field. If 'container' is a class, then this function will
|
||||
* access a static field. If 'container' is a library, then this
|
||||
* function will access a top-level variable.
|
||||
*
|
||||
* This function ignores field visibility (leading underscores in names).
|
||||
*
|
||||
* May generate an unhandled exception error.
|
||||
*
|
||||
* \param container An object, class, or library.
|
||||
* \param name A field name
|
||||
* \param name A field name.
|
||||
*
|
||||
* \return If no error occurs, then the value of the field is
|
||||
* returned. Otherwise an error handle is returned.
|
||||
|
@ -1719,8 +1749,8 @@ DART_EXPORT Dart_Handle Dart_GetField(Dart_Handle container,
|
|||
* May generate an unhandled exception error.
|
||||
*
|
||||
* \param container An object, class, or library.
|
||||
* \param name A field name
|
||||
* \param value The new field value
|
||||
* \param name A field name.
|
||||
* \param value The new field value.
|
||||
*
|
||||
* \return A valid handle if no error occurs.
|
||||
*/
|
||||
|
|
|
@ -2068,6 +2068,118 @@ DART_EXPORT void Dart_ClosureSetSmrck(Dart_Handle object, int64_t value) {
|
|||
// --- Methods and Fields ---
|
||||
|
||||
|
||||
DART_EXPORT Dart_Handle Dart_Invoke(Dart_Handle target,
|
||||
Dart_Handle name,
|
||||
int number_of_arguments,
|
||||
Dart_Handle* arguments) {
|
||||
Isolate* isolate = Isolate::Current();
|
||||
DARTSCOPE(isolate);
|
||||
|
||||
const String& function_name = Api::UnwrapStringHandle(name);
|
||||
if (function_name.IsNull()) {
|
||||
RETURN_TYPE_ERROR(name, String);
|
||||
}
|
||||
if (number_of_arguments < 0) {
|
||||
return Api::NewError(
|
||||
"%s expects argument 'number_of_arguments' to be non-negative.",
|
||||
CURRENT_FUNC);
|
||||
}
|
||||
|
||||
// Check for malformed arguments in the arguments list.
|
||||
GrowableArray<const Object*> dart_args(number_of_arguments);
|
||||
for (int i = 0; i < number_of_arguments; i++) {
|
||||
const Object& arg = Object::Handle(Api::UnwrapHandle(arguments[i]));
|
||||
if (!arg.IsNull() && !arg.IsInstance()) {
|
||||
if (arg.IsError()) {
|
||||
return Api::NewLocalHandle(arg);
|
||||
} else {
|
||||
return Api::NewError(
|
||||
"%s expects argument %d to be an instance of Object.",
|
||||
CURRENT_FUNC, i);
|
||||
}
|
||||
}
|
||||
dart_args.Add(&arg);
|
||||
}
|
||||
|
||||
const Array& kNoArgNames = Array::Handle();
|
||||
const Object& obj = Object::Handle(Api::UnwrapHandle(target));
|
||||
if (obj.IsNull()) {
|
||||
return Api::NewError("%s expects argument 'target' to be non-null.",
|
||||
CURRENT_FUNC);
|
||||
} else if (obj.IsInstance()) {
|
||||
Instance& instance = Instance::Handle();
|
||||
instance ^= obj.raw();
|
||||
const Function& function = Function::Handle(
|
||||
Resolver::ResolveDynamic(instance,
|
||||
function_name,
|
||||
(number_of_arguments + 1),
|
||||
Resolver::kIsQualified));
|
||||
if (function.IsNull()) {
|
||||
const Type& type = Type::Handle(instance.GetType());
|
||||
const String& cls_name = String::Handle(type.ClassName());
|
||||
return Api::NewError("%s: did not find instance method '%s.%s'.",
|
||||
CURRENT_FUNC,
|
||||
cls_name.ToCString(),
|
||||
function_name.ToCString());
|
||||
}
|
||||
const Object& result = Object::Handle(
|
||||
DartEntry::InvokeDynamic(instance, function, dart_args, kNoArgNames));
|
||||
return Api::NewLocalHandle(result);
|
||||
|
||||
} else if (obj.IsClass()) {
|
||||
// Finalize all classes.
|
||||
const char* msg = CheckIsolateState(isolate);
|
||||
if (msg != NULL) {
|
||||
return Api::NewError(msg);
|
||||
}
|
||||
|
||||
Class& cls = Class::Handle();
|
||||
cls ^= obj.raw();
|
||||
const Function& function = Function::Handle(
|
||||
Resolver::ResolveStatic(cls,
|
||||
function_name,
|
||||
number_of_arguments,
|
||||
Array::Handle(),
|
||||
Resolver::kIsQualified));
|
||||
if (function.IsNull()) {
|
||||
const String& cls_name = String::Handle(cls.Name());
|
||||
return Api::NewError("%s: did not find static method '%s.%s'.",
|
||||
CURRENT_FUNC,
|
||||
cls_name.ToCString(),
|
||||
function_name.ToCString());
|
||||
}
|
||||
const Object& result = Object::Handle(
|
||||
DartEntry::InvokeStatic(function, dart_args, kNoArgNames));
|
||||
return Api::NewLocalHandle(result);
|
||||
|
||||
} else if (obj.IsLibrary()) {
|
||||
// Finalize all classes.
|
||||
const char* msg = CheckIsolateState(isolate);
|
||||
if (msg != NULL) {
|
||||
return Api::NewError(msg);
|
||||
}
|
||||
|
||||
Library& lib = Library::Handle();
|
||||
lib ^= obj.raw();
|
||||
const Function& function = Function::Handle(
|
||||
lib.LookupLocalFunction(function_name));
|
||||
if (function.IsNull()) {
|
||||
return Api::NewError("%s: did not find top-level function '%s'.",
|
||||
CURRENT_FUNC,
|
||||
function_name.ToCString());
|
||||
}
|
||||
const Object& result = Object::Handle(
|
||||
DartEntry::InvokeStatic(function, dart_args, kNoArgNames));
|
||||
return Api::NewLocalHandle(result);
|
||||
|
||||
} else {
|
||||
return Api::NewError(
|
||||
"%s expects argument 'target' to be an object, class, or library.",
|
||||
CURRENT_FUNC);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DART_EXPORT Dart_Handle Dart_InvokeStatic(Dart_Handle library_in,
|
||||
Dart_Handle class_name_in,
|
||||
Dart_Handle function_name_in,
|
||||
|
@ -2390,10 +2502,14 @@ DART_EXPORT Dart_Handle Dart_SetField(Dart_Handle container,
|
|||
if (field_name.IsNull()) {
|
||||
RETURN_TYPE_ERROR(name, String);
|
||||
}
|
||||
const Instance& value_instance = Api::UnwrapInstanceHandle(value);
|
||||
if (value_instance.IsNull()) {
|
||||
|
||||
// Since null is allowed for value, we don't use UnwrapInstanceHandle.
|
||||
const Object& value_obj = Object::Handle(Api::UnwrapHandle(value));
|
||||
if (!value_obj.IsNull() && !value_obj.IsInstance()) {
|
||||
RETURN_TYPE_ERROR(value, Instance);
|
||||
}
|
||||
Instance& value_instance = Instance::Handle();
|
||||
value_instance ^= value_obj.raw();
|
||||
|
||||
Field& field = Field::Handle();
|
||||
Function& setter = Function::Handle();
|
||||
|
|
|
@ -2303,6 +2303,43 @@ TEST_CASE(FieldAccess) {
|
|||
}
|
||||
|
||||
|
||||
TEST_CASE(SetField_FunnyValue) {
|
||||
const char* kScriptChars =
|
||||
"var top;\n";
|
||||
|
||||
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
|
||||
Dart_Handle name = Dart_NewString("top");
|
||||
|
||||
Dart_Handle args[1];
|
||||
bool value;
|
||||
|
||||
// Test that you can set the field to a good value.
|
||||
EXPECT_VALID(Dart_SetField(lib, name, Dart_True()));
|
||||
Dart_Handle result = Dart_GetField(lib, name);
|
||||
EXPECT_VALID(result);
|
||||
EXPECT(Dart_IsBoolean(result));
|
||||
EXPECT_VALID(Dart_BooleanValue(result, &value));
|
||||
EXPECT(value);
|
||||
|
||||
// Test that you can set the field to null
|
||||
EXPECT_VALID(Dart_SetField(lib, name, Dart_Null()));
|
||||
result = Dart_GetField(lib, name);
|
||||
EXPECT_VALID(result);
|
||||
EXPECT(Dart_IsNull(result));
|
||||
|
||||
// Pass a non-instance handle.
|
||||
result = Dart_SetField(lib, name, lib);
|
||||
EXPECT(Dart_IsError(result));
|
||||
EXPECT_STREQ("Dart_SetField expects argument 'value' to be of type Instance.",
|
||||
Dart_GetError(result));
|
||||
|
||||
// Pass an error handle. The error is contagious.
|
||||
result = Dart_SetField(lib, name, Api::NewError("myerror"));
|
||||
EXPECT(Dart_IsError(result));
|
||||
EXPECT_STREQ("myerror", Dart_GetError(result));
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE(FieldAccessOld) {
|
||||
const char* kScriptChars =
|
||||
"class Fields {\n"
|
||||
|
@ -2958,6 +2995,149 @@ TEST_CASE(StaticFieldNotFound) {
|
|||
}
|
||||
|
||||
|
||||
TEST_CASE(Invoke) {
|
||||
const char* kScriptChars =
|
||||
"class BaseMethods {\n"
|
||||
" inheritedMethod(arg) => 'inherited $arg';\n"
|
||||
" static nonInheritedMethod(arg) => 'noninherited $arg';\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"class Methods extends BaseMethods {\n"
|
||||
" instanceMethod(arg) => 'instance $arg';\n"
|
||||
" _instanceMethod(arg) => 'hidden instance $arg';\n"
|
||||
" static staticMethod(arg) => 'static $arg';\n"
|
||||
" static _staticMethod(arg) => 'hidden static $arg';\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"topMethod(arg) => 'top $arg';\n"
|
||||
"_topMethod(arg) => 'hidden top $arg';\n"
|
||||
"\n"
|
||||
"Methods test() {\n"
|
||||
" return new Methods();\n"
|
||||
"}\n";
|
||||
|
||||
// Shared setup.
|
||||
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
|
||||
Dart_Handle cls = Dart_GetClass(lib, Dart_NewString("Methods"));
|
||||
EXPECT_VALID(cls);
|
||||
Dart_Handle instance = Dart_Invoke(lib, Dart_NewString("test"), 0, NULL);
|
||||
EXPECT_VALID(instance);
|
||||
Dart_Handle args[1];
|
||||
args[0] = Dart_NewString("!!!");
|
||||
Dart_Handle result;
|
||||
Dart_Handle name;
|
||||
const char* str;
|
||||
|
||||
// Instance method.
|
||||
name = Dart_NewString("instanceMethod");
|
||||
EXPECT(Dart_IsError(Dart_Invoke(lib, name, 1, args)));
|
||||
EXPECT(Dart_IsError(Dart_Invoke(cls, name, 1, args)));
|
||||
result = Dart_Invoke(instance, name, 1, args);
|
||||
EXPECT_VALID(result);
|
||||
result = Dart_StringToCString(result, &str);
|
||||
EXPECT_STREQ("instance !!!", str);
|
||||
|
||||
// Hidden instance method.
|
||||
name = Dart_NewString("_instanceMethod");
|
||||
EXPECT(Dart_IsError(Dart_Invoke(lib, name, 1, args)));
|
||||
EXPECT(Dart_IsError(Dart_Invoke(cls, name, 1, args)));
|
||||
result = Dart_Invoke(instance, name, 1, args);
|
||||
EXPECT_VALID(result);
|
||||
result = Dart_StringToCString(result, &str);
|
||||
EXPECT_STREQ("hidden instance !!!", str);
|
||||
|
||||
// Inherited method.
|
||||
name = Dart_NewString("inheritedMethod");
|
||||
EXPECT(Dart_IsError(Dart_Invoke(lib, name, 1, args)));
|
||||
EXPECT(Dart_IsError(Dart_Invoke(cls, name, 1, args)));
|
||||
result = Dart_Invoke(instance, name, 1, args);
|
||||
EXPECT_VALID(result);
|
||||
result = Dart_StringToCString(result, &str);
|
||||
EXPECT_STREQ("inherited !!!", str);
|
||||
|
||||
// Static method.
|
||||
name = Dart_NewString("staticMethod");
|
||||
EXPECT(Dart_IsError(Dart_Invoke(lib, name, 1, args)));
|
||||
EXPECT(Dart_IsError(Dart_Invoke(instance, name, 1, args)));
|
||||
result = Dart_Invoke(cls, name, 1, args);
|
||||
EXPECT_VALID(result);
|
||||
result = Dart_StringToCString(result, &str);
|
||||
EXPECT_STREQ("static !!!", str);
|
||||
|
||||
// Hidden static method.
|
||||
name = Dart_NewString("_staticMethod");
|
||||
EXPECT(Dart_IsError(Dart_Invoke(lib, name, 1, args)));
|
||||
EXPECT(Dart_IsError(Dart_Invoke(instance, name, 1, args)));
|
||||
result = Dart_Invoke(cls, name, 1, args);
|
||||
EXPECT_VALID(result);
|
||||
result = Dart_StringToCString(result, &str);
|
||||
EXPECT_STREQ("hidden static !!!", str);
|
||||
|
||||
// Static non-inherited method. Not found at any level.
|
||||
name = Dart_NewString("non_inheritedMethod");
|
||||
EXPECT(Dart_IsError(Dart_Invoke(lib, name, 1, args)));
|
||||
EXPECT(Dart_IsError(Dart_Invoke(instance, name, 1, args)));
|
||||
EXPECT(Dart_IsError(Dart_Invoke(cls, name, 1, args)));
|
||||
|
||||
// Top-Level method.
|
||||
name = Dart_NewString("topMethod");
|
||||
EXPECT(Dart_IsError(Dart_Invoke(cls, name, 1, args)));
|
||||
EXPECT(Dart_IsError(Dart_Invoke(instance, name, 1, args)));
|
||||
result = Dart_Invoke(lib, name, 1, args);
|
||||
EXPECT_VALID(result);
|
||||
result = Dart_StringToCString(result, &str);
|
||||
EXPECT_STREQ("top !!!", str);
|
||||
|
||||
// Hidden top-level method.
|
||||
name = Dart_NewString("_topMethod");
|
||||
EXPECT(Dart_IsError(Dart_Invoke(cls, name, 1, args)));
|
||||
EXPECT(Dart_IsError(Dart_Invoke(instance, name, 1, args)));
|
||||
result = Dart_Invoke(lib, name, 1, args);
|
||||
EXPECT_VALID(result);
|
||||
result = Dart_StringToCString(result, &str);
|
||||
EXPECT_STREQ("hidden top !!!", str);
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE(Invoke_FunnyArgs) {
|
||||
const char* kScriptChars =
|
||||
"test(arg) => 'hello $arg';\n";
|
||||
|
||||
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
|
||||
Dart_Handle name = Dart_NewString("test");
|
||||
|
||||
Dart_Handle args[1];
|
||||
const char* str;
|
||||
|
||||
// Make sure that valid args yield valid results.
|
||||
args[0] = Dart_NewString("!!!");
|
||||
Dart_Handle result = Dart_Invoke(lib, Dart_NewString("test"), 1, args);
|
||||
EXPECT_VALID(result);
|
||||
result = Dart_StringToCString(result, &str);
|
||||
EXPECT_STREQ("hello !!!", str);
|
||||
|
||||
// Make sure that null is legal.
|
||||
args[0] = Dart_Null();
|
||||
result = Dart_Invoke(lib, Dart_NewString("test"), 1, args);
|
||||
EXPECT_VALID(result);
|
||||
result = Dart_StringToCString(result, &str);
|
||||
EXPECT_STREQ("hello null", str);
|
||||
|
||||
// Pass a non-instance handle.
|
||||
args[0] = lib;
|
||||
result = Dart_Invoke(lib, Dart_NewString("test"), 1, args);
|
||||
EXPECT(Dart_IsError(result));
|
||||
EXPECT_STREQ("Dart_Invoke expects argument 0 to be an instance of Object.",
|
||||
Dart_GetError(result));
|
||||
|
||||
// Pass an error handle. The error is contagious.
|
||||
args[0] = Api::NewError("myerror");
|
||||
result = Dart_Invoke(lib, Dart_NewString("test"), 1, args);
|
||||
EXPECT(Dart_IsError(result));
|
||||
EXPECT_STREQ("myerror", Dart_GetError(result));
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE(InvokeDynamic) {
|
||||
const char* kScriptChars =
|
||||
"class InvokeDynamic {\n"
|
||||
|
|
Loading…
Reference in a new issue