[dart2wasm] Fix loading unit lookup for top-level constants.

Change-Id: Ia7de84a88efbc53f170ec156046a892310399f58
Tested: Added function_invocation.dart test
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/498380
Commit-Queue: Nate Biggs <natebiggs@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
This commit is contained in:
Nate Biggs
2026-04-28 07:36:44 -07:00
committed by dart-scoped@luci-project-accounts.iam.gserviceaccount.com
parent d93e62b550
commit 6ebcada9ff
4 changed files with 130 additions and 14 deletions
+12 -14
View File
@@ -1818,13 +1818,19 @@ abstract class AstCodeGenerator
w.ValueType visitDynamicInvocation(
DynamicInvocation node,
w.ValueType expectedType,
) {
return _handleDynamicInvocation(node.receiver, node.arguments, node.name);
}
w.ValueType _handleDynamicInvocation(
Expression receiver,
Arguments arguments,
Name memberName,
) {
// Call dynamic invocation forwarder
final receiver = node.receiver;
final typeArguments = node.arguments.types;
final positionalArguments = node.arguments.positional;
final namedArguments = node.arguments.named;
final memberName = node.name;
final typeArguments = arguments.types;
final positionalArguments = arguments.positional;
final namedArguments = arguments.named;
final callShape = MethodCallShape(
memberName,
typeArguments.length,
@@ -2550,15 +2556,7 @@ abstract class AstCodeGenerator
if (node.kind == FunctionAccessKind.Function) {
// Type of function is `Function`, without the argument types.
return visitDynamicInvocation(
DynamicInvocation(
DynamicAccessKind.Dynamic,
node.receiver,
node.name,
node.arguments,
),
expectedType,
);
return _handleDynamicInvocation(node.receiver, node.arguments, node.name);
}
List<String> argNames = node.arguments.named.map((a) => a.name).toList()
@@ -0,0 +1,32 @@
// Copyright (c) 2026, 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.
import 'package:meta/meta.dart';
class EntityId {
final int id;
const EntityId(this.id);
}
EntityId get1<T>(T t) {
return EntityId(1);
}
EntityId get2<T>(T t) {
return EntityId(2);
}
const _idExtractors = <String, Function>{'foo': get1, 'bar': get2};
typedef _IdExtractor<T> = EntityId Function(T thing);
@RecordUse()
_IdExtractor<T> idExtractor<T>(String entityType) {
return (T v) => _idExtractors[entityType]!(v);
}
void main() {
print(idExtractor('foo'));
}
@@ -0,0 +1,43 @@
library #lib;
import self as self;
import "dart:core" as core;
import "package:meta/meta.dart" as meta;
import "package:meta/meta.dart";
class EntityId extends core::Object /*hasConstConstructor*/ {
const constructor •() → self::EntityId
: super core::Object::•()
;
}
[@vm.inferred-return-type.metadata=#lib::EntityId]
static method get1<T extends core::Object? = dynamic>(self::get1::T% t) → self::EntityId {
return new self::EntityId::•();
}
[@vm.inferred-return-type.metadata=#lib::EntityId]
static method get2<T extends core::Object? = dynamic>(self::get2::T% t) → self::EntityId {
return new self::EntityId::•();
}
[@vm.inferred-return-type.metadata=dart.core::_Closure (closure 1 in #lib::idExtractor)]
[@vm.closure-id=1]
[@vm.unboxing-info.metadata=[!regcc]]
@#C1
static method idExtractor<T extends core::Object? = dynamic>([@vm.inferred-type.metadata=dart.core::_OneByteString (value: "foo")] [@vm.inferred-arg-type.metadata=dart.core::_OneByteString (value: "foo")] core::String entityType) → (self::idExtractor::T%) → self::EntityId {
return [@vm.closure-id=1](self::idExtractor::T% v) → self::EntityId => [@vm.inferred-type.metadata=? (receiver not int)] [@vm.direct-call.metadata=dart._compact_hash::__ConstMap&_LinkedHashImmutableBase&MapMixin&_HashBase&_OperatorEqualsAndCanonicalHashCode&_LinkedHashMapMixin&_UnmodifiableMapMixin&_ImmutableLinkedHashMapMixin.[]] [@vm.inferred-type.metadata=dart.core::_Closure? (skip check)] #C6.{core::Map::[]}(entityType){(core::Object?) → core::Function?}!(v) as{TypeError,ForDynamic} self::EntityId;
}
[@vm.inferred-return-type.metadata=dart.core::Null? (value: null)]
static method main() → void {
core::print([@vm.inferred-type.metadata=dart.core::_Closure (closure 1 in #lib::idExtractor)] self::idExtractor<dynamic>("foo"));
}
constants {
#C1 = meta::RecordUse {}
#C2 = "foo"
#C3 = static-tearoff self::get1
#C4 = "bar"
#C5 = static-tearoff self::get2
#C6 = <core::String, core::Function>{#C2:#C3, #C4:#C5}
}
@@ -0,0 +1,43 @@
{
"constants": [
{
"type": "string",
"value": "foo"
}
],
"definitions": [
{
"path": [
{
"disambiguators": [
"static"
],
"kind": "method",
"name": "idExtractor"
}
],
"uri": "package:record_use_test/function_invocation.dart"
}
],
"loading_units": [
{
"name": "1"
}
],
"uses": {
"static_calls": [
{
"definition_index": 0,
"uses": [
{
"loading_unit_index": 0,
"positional": [
0
],
"type": "with_arguments"
}
]
}
]
}
}