diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc index 93d3cfa1128..80029dcb206 100644 --- a/runtime/vm/dart_api_impl.cc +++ b/runtime/vm/dart_api_impl.cc @@ -952,9 +952,9 @@ DART_EXPORT Dart_Result Dart_InvokeDynamic(Dart_Handle object, HandleScope scope; // Setup a VM handle scope. const Object& obj = Object::Handle(Api::UnwrapHandle(object)); if (obj.IsNull()) { - RETURN_FAILURE("Null receiver passed in to invoke dynamic"); - } - if (!obj.IsInstance()) { + // Let the resolver figure out the correct target. + // E.g., (null).toString() should execute correctly. + } else if (!obj.IsInstance()) { RETURN_FAILURE("Invalid receiver (not instance) passed to invoke dynamic"); } if (function_name == NULL) { @@ -972,7 +972,8 @@ DART_EXPORT Dart_Result Dart_InvokeDynamic(Dart_Handle object, (number_of_arguments + 1), 0)); // Named args not yet supported in API. if (function.IsNull()) { - OS::PrintErr("Unable to find instance function: %s\n", function_name); + // TODO(5415268): Invoke noSuchMethod instead of failing. + OS::PrintErr("Unable to find instance function: %s\n", name.ToCString()); RETURN_FAILURE("Unable to find instance function"); } Dart_Result retval; diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc index ab6c950e7e1..929c4652179 100644 --- a/runtime/vm/dart_api_impl_test.cc +++ b/runtime/vm/dart_api_impl_test.cc @@ -1363,6 +1363,41 @@ UNIT_TEST_CASE(InstanceOf) { Dart_ShutdownIsolate(); } + +UNIT_TEST_CASE(NullReceiver) { + Dart_CreateIsolate(NULL, NULL); + Dart_EnterScope(); // Enter a Dart API scope for the unit test. + { + Zone zone; + HandleScope hs; + + Dart_Handle function_name = Dart_NewString("toString"); + const int number_of_arguments = 0; + Dart_Handle null_receiver = Api::NewLocalHandle(Object::Handle()); + Dart_Handle dart_arguments[0]; + Dart_Result result = Dart_InvokeDynamic(null_receiver, + function_name, + number_of_arguments, + dart_arguments); + EXPECT(Dart_IsValidResult(result)); + Dart_Handle retobj = Dart_GetResult(result); + EXPECT(Dart_IsString(retobj)); + + // Should throw a NullPointerException. Disabled due to bug 5415268. + /* + Dart_Handle function_name2 = Dart_NewString("NoNoNo"); + result = Dart_InvokeDynamic(null_receiver, + function_name2, + number_of_arguments, + dart_arguments); + EXPECT(Dart_IsValidResult(result)); + retobj = Dart_GetResult(result); + EXPECT(Dart_ExceptionOccurred(retobj)); */ + } + Dart_ExitScope(); // Exit the Dart API scope. + Dart_ShutdownIsolate(); +} + #endif // TARGET_ARCH_IA32. } // namespace dart