diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc index b8a123eb9a7..9f2dfe5433c 100644 --- a/runtime/lib/mirrors.cc +++ b/runtime/lib/mirrors.cc @@ -54,14 +54,14 @@ static void ThrowNoSuchMethod(const Instance& receiver, const Smi& invocation_type = Smi::Handle(Smi::New(InvocationMirror::EncodeType(level, kind))); - const Array& args = Array::Handle(Array::New(6)); + const Array& args = Array::Handle(Array::New(7)); args.SetAt(0, receiver); args.SetAt(1, function_name); args.SetAt(2, invocation_type); - // TODO(regis): Support invocation of generic functions with type arguments. - args.SetAt(3, Object::null_type_arguments()); - args.SetAt(4, arguments); - args.SetAt(5, argument_names); + args.SetAt(3, Object::smi_zero()); // Type arguments length. + args.SetAt(4, Object::null_type_arguments()); + args.SetAt(5, arguments); + args.SetAt(6, argument_names); const Library& libcore = Library::Handle(Library::CoreLibrary()); const Class& NoSuchMethodError = diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc index 0ea4e895c80..121aff8107e 100644 --- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc +++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc @@ -1685,8 +1685,9 @@ Fragment StreamingFlowGraphBuilder::RethrowException(TokenPosition position, return flow_graph_builder_->RethrowException(position, catch_try_index); } -Fragment StreamingFlowGraphBuilder::ThrowNoSuchMethodError() { - return flow_graph_builder_->ThrowNoSuchMethodError(); +Fragment StreamingFlowGraphBuilder::ThrowNoSuchMethodError( + const Function& target) { + return flow_graph_builder_->ThrowNoSuchMethodError(target); } Fragment StreamingFlowGraphBuilder::Constant(const Object& value) { @@ -1715,32 +1716,12 @@ Fragment StreamingFlowGraphBuilder::CheckNull( clear_the_temp); } -static void BadArity(const Script& script, - TokenPosition position, - const String& error_message) { -#ifndef PRODUCT - // TODO(https://github.com/dart-lang/sdk/issues/37517): Should emit code to - // throw a NoSuchMethodError. - // Correct arity is checked at compile time by CFE. However, an isolate reload - // after an arity change may lead here. - // Using strong mode with a mix of opted in and opted out libraries may - // also result in this error undetected by CFE. - Isolate* isolate = Isolate::Current(); - ASSERT(isolate->HasAttemptedReload() || isolate->null_safety()); - Report::MessageF(Report::kError, script, position, Report::AtLocation, - "Static call with invalid arguments: %s", - error_message.ToCString()); -#endif - UNREACHABLE(); -} - Fragment StreamingFlowGraphBuilder::StaticCall(TokenPosition position, const Function& target, intptr_t argument_count, ICData::RebindRule rebind_rule) { - String& error_message = String::Handle(); - if (!target.AreValidArgumentCounts(0, argument_count, 0, &error_message)) { - BadArity(script_, position, error_message); + if (!target.AreValidArgumentCounts(0, argument_count, 0, nullptr)) { + return flow_graph_builder_->ThrowNoSuchMethodError(target); } return flow_graph_builder_->StaticCall(position, target, argument_count, rebind_rule); @@ -1755,10 +1736,9 @@ Fragment StreamingFlowGraphBuilder::StaticCall( const InferredTypeMetadata* result_type, intptr_t type_args_count, bool use_unchecked_entry) { - String& error_message = String::Handle(); if (!target.AreValidArguments(type_args_count, argument_count, argument_names, - &error_message)) { - BadArity(script_, position, error_message); + nullptr)) { + return flow_graph_builder_->ThrowNoSuchMethodError(target); } return flow_graph_builder_->StaticCall( position, target, argument_count, argument_names, rebind_rule, diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h index fbba4d67c6d..d694a83f5f0 100644 --- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h +++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h @@ -166,7 +166,7 @@ class StreamingFlowGraphBuilder : public KernelReaderHelper { intptr_t yield_index = PcDescriptorsLayout::kInvalidYieldIndex); Fragment EvaluateAssertion(); Fragment RethrowException(TokenPosition position, int catch_try_index); - Fragment ThrowNoSuchMethodError(); + Fragment ThrowNoSuchMethodError(const Function& target); Fragment Constant(const Object& value); Fragment IntConstant(int64_t value); Fragment LoadStaticField(const Field& field); diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc index 62ce5a75552..35e2fadb48f 100644 --- a/runtime/vm/compiler/frontend/kernel_to_il.cc +++ b/runtime/vm/compiler/frontend/kernel_to_il.cc @@ -392,7 +392,7 @@ Fragment FlowGraphBuilder::ThrowException(TokenPosition position) { instructions += Fragment(new (Z) ThrowInstr(position, GetNextDeoptId(), exception)) .closed(); - // Use it's side effect of leaving a constant on the stack (does not change + // Use its side effect of leaving a constant on the stack (does not change // the graph). NullConstant(); @@ -408,7 +408,7 @@ Fragment FlowGraphBuilder::RethrowException(TokenPosition position, Fragment(new (Z) ReThrowInstr(position, catch_try_index, GetNextDeoptId(), exception, stacktrace)) .closed(); - // Use it's side effect of leaving a constant on the stack (does not change + // Use its side effect of leaving a constant on the stack (does not change // the graph). NullConstant(); @@ -678,7 +678,7 @@ Fragment FlowGraphBuilder::ThrowTypeError() { return instructions; } -Fragment FlowGraphBuilder::ThrowNoSuchMethodError() { +Fragment FlowGraphBuilder::ThrowNoSuchMethodError(const Function& target) { const Class& klass = Class::ZoneHandle( Z, Library::LookupCoreClass(Symbols::NoSuchMethodError())); ASSERT(!klass.IsNull()); @@ -688,20 +688,36 @@ Fragment FlowGraphBuilder::ThrowNoSuchMethodError() { Fragment instructions; - // Call NoSuchMethodError._throwNew static function. - instructions += NullConstant(); // receiver + const Class& owner = Class::Handle(Z, target.Owner()); + AbstractType& receiver = AbstractType::ZoneHandle(); + InvocationMirror::Kind kind = InvocationMirror::Kind::kMethod; + InvocationMirror::Level level; + if (owner.IsTopLevel()) { + level = InvocationMirror::Level::kTopLevel; + } else { + receiver = owner.RareType(); + if (target.kind() == FunctionLayout::kConstructor) { + level = InvocationMirror::Level::kConstructor; + } else { + level = InvocationMirror::Level::kStatic; + } + } - instructions += - Constant(H.DartString("", Heap::kOld)); // memberName - instructions += IntConstant(-1); // invocation_type - instructions += NullConstant(); // type arguments - instructions += NullConstant(); // arguments - instructions += NullConstant(); // argumentNames + // Call NoSuchMethodError._throwNew static function. + instructions += Constant(receiver); // receiver + instructions += Constant(String::ZoneHandle(Z, target.name())); // memberName + instructions += IntConstant(InvocationMirror::EncodeType(level, kind)); + instructions += IntConstant(0); // type arguments length + instructions += NullConstant(); // type arguments + instructions += NullConstant(); // arguments + instructions += NullConstant(); // argumentNames instructions += StaticCall(TokenPosition::kNoSource, throw_function, - /* argument_count = */ 6, ICData::kStatic); - // Leave "result" on the stack since callers expect it to be there (even - // though the function will result in an exception). + /* argument_count = */ 7, ICData::kStatic); + + // Properly close graph with a ThrowInstr, although it is not executed. + instructions += ThrowException(TokenPosition::kNoSource); + instructions += Drop(); return instructions; } diff --git a/runtime/vm/compiler/frontend/kernel_to_il.h b/runtime/vm/compiler/frontend/kernel_to_il.h index f6f08e5d1e2..fbee8532bdb 100644 --- a/runtime/vm/compiler/frontend/kernel_to_il.h +++ b/runtime/vm/compiler/frontend/kernel_to_il.h @@ -164,7 +164,7 @@ class FlowGraphBuilder : public BaseFlowGraphBuilder { bool use_unchecked_entry = false); Fragment StringInterpolateSingle(TokenPosition position); Fragment ThrowTypeError(); - Fragment ThrowNoSuchMethodError(); + Fragment ThrowNoSuchMethodError(const Function& target); Fragment ThrowLateInitializationError(TokenPosition position, const String& name); Fragment BuildImplicitClosureCreation(const Function& target); diff --git a/runtime/vm/isolate_reload_test.cc b/runtime/vm/isolate_reload_test.cc index 5f16ca6b66b..72411fb00c4 100644 --- a/runtime/vm/isolate_reload_test.cc +++ b/runtime/vm/isolate_reload_test.cc @@ -4516,7 +4516,9 @@ TEST_CASE(IsolateReload_StaticTargetArityChange) { lib = TestCase::ReloadTestScript(kReloadScript); EXPECT_VALID(lib); EXPECT_ERROR(SimpleInvokeError(lib, "main"), - "Static call with invalid arguments"); + "Unhandled exception:\n" + "NoSuchMethodError: No constructor 'A.' " + "with matching arguments declared in class 'A'."); } #endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME) diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc index 84112b10f39..c6515e16285 100644 --- a/runtime/vm/object.cc +++ b/runtime/vm/object.cc @@ -3907,14 +3907,14 @@ static ObjectPtr ThrowNoSuchMethod(const Instance& receiver, const Smi& invocation_type = Smi::Handle(Smi::New(InvocationMirror::EncodeType(level, kind))); - const Array& args = Array::Handle(Array::New(6)); + const Array& args = Array::Handle(Array::New(7)); args.SetAt(0, receiver); args.SetAt(1, function_name); args.SetAt(2, invocation_type); - // TODO(regis): Support invocation of generic functions with type arguments. - args.SetAt(3, Object::null_type_arguments()); - args.SetAt(4, arguments); - args.SetAt(5, argument_names); + args.SetAt(3, Object::smi_zero()); // Type arguments length. + args.SetAt(4, Object::null_type_arguments()); + args.SetAt(5, arguments); + args.SetAt(6, argument_names); const Library& libcore = Library::Handle(Library::CoreLibrary()); const Class& NoSuchMethodError = diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc index ecd35ca5008..36ec9f8455b 100644 --- a/runtime/vm/runtime_entry.cc +++ b/runtime/vm/runtime_entry.cc @@ -179,13 +179,14 @@ static void NullErrorHelper(Zone* zone, const String& selector) { zone, Smi::New(InvocationMirror::EncodeType(InvocationMirror::kDynamic, kind))); - const Array& args = Array::Handle(zone, Array::New(6)); + const Array& args = Array::Handle(zone, Array::New(7)); args.SetAt(0, /* instance */ Object::null_object()); args.SetAt(1, selector); args.SetAt(2, invocation_type); - args.SetAt(3, /* func_type_args */ Object::null_object()); - args.SetAt(4, /* func_args */ Object::null_object()); - args.SetAt(5, /* func_arg_names */ Object::null_object()); + args.SetAt(3, /* func_type_args_length */ Object::smi_zero()); + args.SetAt(4, /* func_type_args */ Object::null_object()); + args.SetAt(5, /* func_args */ Object::null_object()); + args.SetAt(6, /* func_arg_names */ Object::null_object()); Exceptions::ThrowByType(Exceptions::kNoSuchMethod, args); } diff --git a/sdk/lib/_internal/vm/lib/errors_patch.dart b/sdk/lib/_internal/vm/lib/errors_patch.dart index 1ffcfa13720..add6b295db9 100644 --- a/sdk/lib/_internal/vm/lib/errors_patch.dart +++ b/sdk/lib/_internal/vm/lib/errors_patch.dart @@ -180,12 +180,6 @@ class AbstractClassInstantiationError { @patch class NoSuchMethodError { - // Deprecated members to be removed. - Symbol _memberName; - List _arguments; - Map _namedArguments; - List _existingArgumentNames; - final Object _receiver; final Invocation _invocation; @@ -202,44 +196,29 @@ class NoSuchMethodError { // method at compile time. The receiver is actually the literal class of the // unresolved method. @pragma("vm:entry-point", "call") - static void _throwNew(Object receiver, String memberName, int invocation_type, - Object typeArguments, List arguments, List argumentNames) { - throw new NoSuchMethodError._withType(receiver, memberName, invocation_type, - typeArguments, arguments, argumentNames); - } - - static void _throwNewIfNotLoaded( - _LibraryPrefix prefix, + static void _throwNew( Object receiver, String memberName, - int invocation_type, + int invocationType, + int typeArgumentsLength, Object typeArguments, List arguments, List argumentNames) { - if (!prefix.isLoaded()) { - _throwNew(receiver, memberName, invocation_type, typeArguments, arguments, - argumentNames); - } + throw new NoSuchMethodError._withType(receiver, memberName, invocationType, + typeArgumentsLength, typeArguments, arguments, argumentNames); } - // TODO(regis): Deprecated member still used by dart2js to be removed. - // Remember the type from the invocation mirror or static compilation - // analysis when thrown directly with _throwNew. A negative value means - // that no information is available. - int _invocation_type; - - // TODO(regis): Deprecated constructor still used by dart2js to be removed. + // Deprecated constructor. @patch - NoSuchMethodError(Object receiver, Symbol memberName, - List positionalArguments, Map namedArguments, - [List existingArgumentNames = null]) - : _receiver = receiver, - _invocation = null, - _memberName = memberName, - _arguments = positionalArguments, - _namedArguments = namedArguments, - _existingArgumentNames = existingArgumentNames, - _invocation_type = -1; + NoSuchMethodError(this._receiver, Symbol memberName, List positionalArguments, + Map namedArguments, + [List existingArgumentNames = null]) // existingArgumentNames ignored. + : this._invocation = new _InvocationMirror._withType( + memberName, + _InvocationMirror._UNINITIALIZED, + null, // Type arguments not supported in deprecated constructor. + positionalArguments, + namedArguments); // Helper to build a map of named arguments. static Map _NamedArgumentsMap( @@ -247,8 +226,8 @@ class NoSuchMethodError { Map namedArguments = new Map(); int numPositionalArguments = arguments.length - argumentNames.length; for (int i = 0; i < argumentNames.length; i++) { - var arg_value = arguments[numPositionalArguments + i]; - namedArguments[new Symbol(argumentNames[i])] = arg_value; + final argValue = arguments[numPositionalArguments + i]; + namedArguments[new Symbol(argumentNames[i])] = argValue; } return namedArguments; } @@ -261,17 +240,16 @@ class NoSuchMethodError { NoSuchMethodError._withType( this._receiver, String memberName, - int invocation_type, + int invocationType, + int typeArgumentsLength, // Needed with all-dynamic (null) typeArguments. Object typeArguments, List arguments, List argumentNames) : this._invocation = new _InvocationMirror._withType( new Symbol(memberName), - invocation_type, - typeArguments != null - // TODO(33073): Use actual count of type arguments in place of 0. - ? _InvocationMirror._unpackTypeArguments(typeArguments, 0) - : null, + invocationType, + _InvocationMirror._unpackTypeArguments( + typeArguments, typeArgumentsLength), argumentNames != null ? arguments.sublist(0, arguments.length - argumentNames.length) : arguments, @@ -284,12 +262,7 @@ class NoSuchMethodError { @patch String toString() { - // TODO(regis): Remove this null check once dart2js is updated. var invocation = _invocation; - if (invocation == null) { - // Use deprecated version of toString. - return _toStringDeprecated(); - } if (invocation is _InvocationMirror) { String memberName = internal.Symbol.computeUnmangledName(invocation.memberName); @@ -341,7 +314,7 @@ class NoSuchMethodError { _existingMethodSignature(_receiver, memberName, invocation._type); String argsMsg = existingSig != null ? " with matching arguments" : ""; - String kindBuf; + String kindBuf = "function"; if (kind >= 0 && kind < 5) { kindBuf = (const [ "method", @@ -452,7 +425,8 @@ class NoSuchMethodError { var name = _symbolToString(invocation.memberName); var receiverType = "${receiver.runtimeType}"; if (invocation.isAccessor) { - return "NoSuchMethodError: $receiverType has no $name ${invocation.isGetter ? "getter" : "setter"}"; + return "NoSuchMethodError: $receiverType has no $name " + "${invocation.isGetter ? "getter" : "setter"}"; } var buffer = StringBuffer("NoSuchMethodError")..write(": "); buffer.write("$receiverType has no $name method accepting arguments "); @@ -490,145 +464,6 @@ class NoSuchMethodError { } return "$symbol"; } - - // TODO(regis): Remove this function once dart2js is updated. - String _toStringDeprecated() { - var level = (_invocation_type >> _InvocationMirror._LEVEL_SHIFT) & - _InvocationMirror._LEVEL_MASK; - var type = _invocation_type & _InvocationMirror._KIND_MASK; - String memberName = (_memberName == null) - ? "" - : internal.Symbol.computeUnmangledName(_memberName); - - if (type == _InvocationMirror._LOCAL_VAR) { - return "NoSuchMethodError: Cannot assign to final variable '$memberName'"; - } - - StringBuffer arguments = new StringBuffer(); - int argumentCount = 0; - if (_arguments != null) { - for (; argumentCount < _arguments.length; argumentCount++) { - if (argumentCount > 0) { - arguments.write(", "); - } - arguments.write(Error.safeToString(_arguments[argumentCount])); - } - } - if (_namedArguments != null) { - _namedArguments.forEach((Symbol key, var value) { - if (argumentCount > 0) { - arguments.write(", "); - } - arguments.write(internal.Symbol.computeUnmangledName(key)); - arguments.write(": "); - arguments.write(Error.safeToString(value)); - argumentCount++; - }); - } - bool argsMismatch = _existingArgumentNames != null; - String argsMessage = argsMismatch ? " with matching arguments" : ""; - - String type_str; - if (type >= 0 && type < 5) { - type_str = (const [ - "method", - "getter", - "setter", - "getter or setter", - "variable" - ])[type]; - } - - StringBuffer msg_buf = new StringBuffer("NoSuchMethodError: "); - bool is_type_call = false; - switch (level) { - case _InvocationMirror._DYNAMIC: - { - if (_receiver == null) { - if (argsMismatch) { - msg_buf.writeln("The null object does not have a $type_str " - "'$memberName'$argsMessage."); - } else { - msg_buf - .writeln("The $type_str '$memberName' was called on null."); - } - } else { - if (_receiver is _Closure) { - msg_buf.writeln("Closure call with mismatched arguments: " - "function '$memberName'"); - } else if (_receiver is _Type && memberName == "call") { - is_type_call = true; - String name = _receiver.toString(); - msg_buf.writeln("Attempted to use type '$name' as a function. " - "Since types do not define a method 'call', this is not " - "possible. Did you intend to call the $name constructor and " - "forget the 'new' operator?"); - } else { - msg_buf - .writeln("Class '${_receiver.runtimeType}' has no instance " - "$type_str '$memberName'$argsMessage."); - } - } - break; - } - case _InvocationMirror._SUPER: - { - msg_buf.writeln("Super class of class '${_receiver.runtimeType}' has " - "no instance $type_str '$memberName'$argsMessage."); - memberName = "super.$memberName"; - break; - } - case _InvocationMirror._STATIC: - { - msg_buf.writeln("No static $type_str '$memberName'$argsMessage " - "declared in class '$_receiver'."); - break; - } - case _InvocationMirror._CONSTRUCTOR: - { - msg_buf.writeln("No constructor '$memberName'$argsMessage declared " - "in class '$_receiver'."); - memberName = "new $memberName"; - break; - } - case _InvocationMirror._TOP_LEVEL: - { - msg_buf.writeln("No top-level $type_str '$memberName'$argsMessage " - "declared."); - break; - } - } - - if (level == _InvocationMirror._TOP_LEVEL) { - msg_buf.writeln("Receiver: top-level"); - } else { - msg_buf.writeln("Receiver: ${Error.safeToString(_receiver)}"); - } - - if (type == _InvocationMirror._METHOD) { - String m = is_type_call ? "$_receiver" : "$memberName"; - msg_buf.write("Tried calling: $m($arguments)"); - } else if (argumentCount == 0) { - msg_buf.write("Tried calling: $memberName"); - } else if (type == _InvocationMirror._SETTER) { - msg_buf.write("Tried calling: $memberName$arguments"); - } else { - msg_buf.write("Tried calling: $memberName = $arguments"); - } - - if (argsMismatch) { - StringBuffer formalParameters = new StringBuffer(); - for (int i = 0; i < _existingArgumentNames.length; i++) { - if (i > 0) { - formalParameters.write(", "); - } - formalParameters.write(_existingArgumentNames[i]); - } - msg_buf.write("\nFound: $memberName($formalParameters)"); - } - - return msg_buf.toString(); - } } @pragma("vm:entry-point") diff --git a/sdk/lib/_internal/vm/lib/invocation_mirror_patch.dart b/sdk/lib/_internal/vm/lib/invocation_mirror_patch.dart index cfa7a6d6b22..1f43d545969 100644 --- a/sdk/lib/_internal/vm/lib/invocation_mirror_patch.dart +++ b/sdk/lib/_internal/vm/lib/invocation_mirror_patch.dart @@ -12,6 +12,7 @@ class _InvocationMirror implements Invocation { // Constants describing the invocation kind. // _FIELD cannot be generated by regular invocation mirrors. + static const int _UNINITIALIZED = -1; static const int _METHOD = 0; static const int _GETTER = 1; static const int _SETTER = 2; @@ -48,7 +49,7 @@ class _InvocationMirror implements Invocation { // External representation of the invocation mirror; populated on demand. Symbol _memberName; - int _type; + int _type = _UNINITIALIZED; List _typeArguments; List _positionalArguments; Map _namedArguments; @@ -61,7 +62,9 @@ class _InvocationMirror implements Invocation { } void _setMemberNameAndType() { - _type ??= 0; + if (_type == _UNINITIALIZED) { + _type = 0; + } if (_functionName.startsWith("get:")) { _type |= _GETTER; _memberName = new internal.Symbol.unvalidated(_functionName.substring(4)); @@ -144,28 +147,28 @@ class _InvocationMirror implements Invocation { } bool get isMethod { - if (_type == null) { + if (_type == _UNINITIALIZED) { _setMemberNameAndType(); } return (_type & _KIND_MASK) == _METHOD; } bool get isAccessor { - if (_type == null) { + if (_type == _UNINITIALIZED) { _setMemberNameAndType(); } return (_type & _KIND_MASK) != _METHOD; } bool get isGetter { - if (_type == null) { + if (_type == _UNINITIALIZED) { _setMemberNameAndType(); } return (_type & _KIND_MASK) == _GETTER; } bool get isSetter { - if (_type == null) { + if (_type == _UNINITIALIZED) { _setMemberNameAndType(); } return (_type & _KIND_MASK) == _SETTER; @@ -182,7 +185,7 @@ class _InvocationMirror implements Invocation { @pragma("vm:entry-point", "call") static _allocateInvocationMirror(String functionName, List argumentsDescriptor, List arguments, bool isSuperInvocation, - [int type = null]) { + [int type = _UNINITIALIZED]) { return new _InvocationMirror( functionName, argumentsDescriptor, arguments, isSuperInvocation, type); } @@ -200,6 +203,6 @@ class _InvocationMirror implements Invocation { int type, int delayedTypeArgumentsLen) { return new _InvocationMirror(functionName, argumentsDescriptor, arguments, - false, type, delayedTypeArgumentsLen); + false, type ?? _UNINITIALIZED, delayedTypeArgumentsLen); } } diff --git a/sdk_nnbd/lib/_internal/vm/lib/errors_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/errors_patch.dart index 05983d7a616..c4b91f205e3 100644 --- a/sdk_nnbd/lib/_internal/vm/lib/errors_patch.dart +++ b/sdk_nnbd/lib/_internal/vm/lib/errors_patch.dart @@ -177,22 +177,15 @@ class AbstractClassInstantiationError { @patch class NoSuchMethodError { - // Deprecated members to be removed. - Symbol? _memberName; - List? _arguments; - Map? _namedArguments; - List? _existingArgumentNames; + final Object? _receiver; + final Invocation _invocation; - final Object _receiver; - final Invocation? _invocation; - - // Issue(dartbug.com/127160): Remove the cast to [_InvocationMirror]. @patch - NoSuchMethodError.withInvocation(Object receiver, Invocation invocation) + NoSuchMethodError.withInvocation(Object? receiver, Invocation invocation) : _receiver = receiver, _invocation = invocation; - static void _throwNewInvocation(Object receiver, Invocation invocation) { + static void _throwNewInvocation(Object? receiver, Invocation invocation) { throw new NoSuchMethodError.withInvocation(receiver, invocation); } @@ -200,44 +193,29 @@ class NoSuchMethodError { // method at compile time. The receiver is actually the literal class of the // unresolved method. @pragma("vm:entry-point", "call") - static void _throwNew(Object receiver, String memberName, int invocationType, - Object? typeArguments, List? arguments, List? argumentNames) { - throw new NoSuchMethodError._withType(receiver, memberName, invocationType, - typeArguments, arguments, argumentNames); - } - - static void _throwNewIfNotLoaded( - _LibraryPrefix prefix, + static void _throwNew( Object receiver, String memberName, int invocationType, - Object typeArguments, - List arguments, - List argumentNames) { - if (!prefix.isLoaded()) { - _throwNew(receiver, memberName, invocationType, typeArguments, arguments, - argumentNames); - } + int typeArgumentsLength, + Object? typeArguments, + List? arguments, + List? argumentNames) { + throw new NoSuchMethodError._withType(receiver, memberName, invocationType, + typeArgumentsLength, typeArguments, arguments, argumentNames); } - // TODO(regis): Deprecated member still used by dart2js to be removed. - // Remember the type from the invocation mirror or static compilation - // analysis when thrown directly with _throwNew. A negative value means - // that no information is available. - int _invocationType = -1; - - // TODO(regis): Deprecated constructor still used by dart2js to be removed. + // Deprecated constructor. @patch - NoSuchMethodError(Object receiver, Symbol memberName, - List positionalArguments, Map namedArguments, - [List? existingArgumentNames = null]) - : _receiver = receiver, - _invocation = null, - _memberName = memberName, - _arguments = positionalArguments, - _namedArguments = namedArguments, - _existingArgumentNames = existingArgumentNames, - _invocationType = -1; + NoSuchMethodError(this._receiver, Symbol memberName, + List? positionalArguments, Map? namedArguments, + [List? existingArgumentNames = null]) // existingArgumentNames ignored. + : this._invocation = new _InvocationMirror._withType( + memberName, + _InvocationMirror._UNINITIALIZED, + null, // Type arguments not supported in deprecated constructor. + positionalArguments, + namedArguments); // Helper to build a map of named arguments. static Map _NamedArgumentsMap( @@ -260,16 +238,15 @@ class NoSuchMethodError { this._receiver, String memberName, int invocationType, + int typeArgumentsLength, // Needed with all-dynamic (null) typeArguments. Object? typeArguments, List? arguments, List? argumentNames) : this._invocation = new _InvocationMirror._withType( new Symbol(memberName), invocationType, - typeArguments != null - // TODO(33073): Use actual count of type arguments in place of 0. - ? _InvocationMirror._unpackTypeArguments(typeArguments, 0) - : null, + _InvocationMirror._unpackTypeArguments( + typeArguments, typeArgumentsLength), argumentNames != null ? arguments!.sublist(0, arguments.length - argumentNames.length) : arguments, @@ -277,17 +254,12 @@ class NoSuchMethodError { ? _NamedArgumentsMap(arguments!, argumentNames) : null); - static String? _existingMethodSignature(Object receiver, String methodName, + static String? _existingMethodSignature(Object? receiver, String methodName, int invocationType) native "NoSuchMethodError_existingMethodSignature"; @patch String toString() { - // TODO(regis): Remove this null check once dart2js is updated. final localInvocation = _invocation; - if (localInvocation == null) { - // Use deprecated version of toString. - return _toStringDeprecated(); - } if (localInvocation is _InvocationMirror) { var internalName = localInvocation.memberName as internal.Symbol; String memberName = internal.Symbol.computeUnmangledName(internalName); @@ -343,14 +315,16 @@ class NoSuchMethodError { _receiver, memberName, localInvocation._type); String argsMsg = existingSig != null ? " with matching arguments" : ""; - assert(kind >= 0 && kind < 5); - final String kindBuf = (const [ - "method", - "getter", - "setter", - "getter or setter", - "variable" - ])[kind]; + String kindBuf = "function"; + if (kind >= 0 && kind < 5) { + kindBuf = (const [ + "method", + "getter", + "setter", + "getter or setter", + "variable" + ])[kind]; + } StringBuffer msgBuf = new StringBuffer("NoSuchMethodError: "); bool isTypeCall = false; @@ -448,7 +422,7 @@ class NoSuchMethodError { /// Used for situations where there is no extra information available /// about the failed invocation than the [Invocation] object and receiver, /// which includes errors created using [NoSuchMethodError.withInvocation]. - static String _toStringPlain(Object receiver, Invocation invocation) { + static String _toStringPlain(Object? receiver, Invocation invocation) { var name = _symbolToString(invocation.memberName); var receiverType = "${receiver.runtimeType}"; if (invocation.isAccessor) { @@ -491,143 +465,6 @@ class NoSuchMethodError { } return "$symbol"; } - - // TODO(regis): Remove this function once dart2js is updated. - String _toStringDeprecated() { - var level = (_invocationType >> _InvocationMirror._LEVEL_SHIFT) & - _InvocationMirror._LEVEL_MASK; - var type = _invocationType & _InvocationMirror._KIND_MASK; - String memberName = (_memberName == null) - ? "" - : internal.Symbol.computeUnmangledName(_memberName as internal.Symbol); - - if (type == _InvocationMirror._LOCAL_VAR) { - return "NoSuchMethodError: Cannot assign to final variable '$memberName'"; - } - - StringBuffer arguments = new StringBuffer(); - int argumentCount = 0; - final args = _arguments; - if (args != null) { - for (; argumentCount < args.length; argumentCount++) { - if (argumentCount > 0) { - arguments.write(", "); - } - arguments.write(Error.safeToString(args[argumentCount])); - } - } - _namedArguments?.forEach((Symbol key, var value) { - if (argumentCount > 0) { - arguments.write(", "); - } - var internalName = key as internal.Symbol; - arguments.write(internal.Symbol.computeUnmangledName(internalName)); - arguments.write(": "); - arguments.write(Error.safeToString(value)); - argumentCount++; - }); - bool argsMismatch = _existingArgumentNames != null; - String argsMessage = argsMismatch ? " with matching arguments" : ""; - - final String typeStr = (type >= 0 && type < 5) - ? (const [ - "method", - "getter", - "setter", - "getter or setter", - "variable" - ])[type] - : ""; - - StringBuffer msgBuf = new StringBuffer("NoSuchMethodError: "); - bool isTypeCall = false; - switch (level) { - case _InvocationMirror._DYNAMIC: - { - if (_receiver == null) { - if (argsMismatch) { - msgBuf.writeln("The null object does not have a $typeStr " - "'$memberName'$argsMessage."); - } else { - msgBuf.writeln("The $typeStr '$memberName' was called on null."); - } - } else { - if (_receiver is _Closure) { - msgBuf.writeln("Closure call with mismatched arguments: " - "function '$memberName'"); - } else if (_receiver is _Type && memberName == "call") { - isTypeCall = true; - String name = _receiver.toString(); - msgBuf.writeln("Attempted to use type '$name' as a function. " - "Since types do not define a method 'call', this is not " - "possible. Did you intend to call the $name constructor and " - "forget the 'new' operator?"); - } else { - msgBuf.writeln("Class '${_receiver.runtimeType}' has no instance " - "$typeStr '$memberName'$argsMessage."); - } - } - break; - } - case _InvocationMirror._SUPER: - { - msgBuf.writeln("Super class of class '${_receiver.runtimeType}' has " - "no instance $typeStr '$memberName'$argsMessage."); - memberName = "super.$memberName"; - break; - } - case _InvocationMirror._STATIC: - { - msgBuf.writeln("No static $typeStr '$memberName'$argsMessage " - "declared in class '$_receiver'."); - break; - } - case _InvocationMirror._CONSTRUCTOR: - { - msgBuf.writeln("No constructor '$memberName'$argsMessage declared " - "in class '$_receiver'."); - memberName = "new $memberName"; - break; - } - case _InvocationMirror._TOP_LEVEL: - { - msgBuf.writeln("No top-level $typeStr '$memberName'$argsMessage " - "declared."); - break; - } - } - - if (level == _InvocationMirror._TOP_LEVEL) { - msgBuf.writeln("Receiver: top-level"); - } else { - msgBuf.writeln("Receiver: ${Error.safeToString(_receiver)}"); - } - - if (type == _InvocationMirror._METHOD) { - String m = isTypeCall ? "$_receiver" : "$memberName"; - msgBuf.write("Tried calling: $m($arguments)"); - } else if (argumentCount == 0) { - msgBuf.write("Tried calling: $memberName"); - } else if (type == _InvocationMirror._SETTER) { - msgBuf.write("Tried calling: $memberName$arguments"); - } else { - msgBuf.write("Tried calling: $memberName = $arguments"); - } - - if (argsMismatch) { - StringBuffer formalParameters = new StringBuffer(); - final argumentNames = _existingArgumentNames!; - for (int i = 0; i < argumentNames.length; i++) { - if (i > 0) { - formalParameters.write(", "); - } - formalParameters.write(argumentNames[i]); - } - msgBuf.write("\nFound: $memberName($formalParameters)"); - } - - return msgBuf.toString(); - } } @pragma("vm:entry-point")