diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart index c42efafb911..1b8e2531183 100644 --- a/pkg/compiler/lib/src/ssa/codegen.dart +++ b/pkg/compiler/lib/src/ssa/codegen.dart @@ -2677,6 +2677,15 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { ? _nativeData.getFixedBackendName(target) : target.name; + Object? recordedMethodUses; + if (_closedWorld.annotationsData.shouldRecordMethodUses(target)) { + recordedMethodUses = _recordMethodUses( + target, + inputs, + node.sourceInformation!, + ); + } + void invokeWithJavaScriptReceiver(js.Expression receiverExpression) { // JS-interop target names can be paths ("a.b"), so we parse them to // re-associate the property accesses ("#.a.b" is `dot(dot(#,'a'),'b')`). @@ -2706,6 +2715,9 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { js.Expression expression = js.js .uncachedExpressionTemplate(template) .instantiateExpression(templateInputs); + if (recordedMethodUses != null) { + expression = expression.withAnnotation(recordedMethodUses); + } push(expression.withSourceInformation(node.sourceInformation)); _registry.registerNativeMethod(target); } @@ -2743,6 +2755,9 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { assert(target.isFunction); expression = js.js('#(#)', [targetExpression, arguments]); } + if (recordedMethodUses != null) { + expression = expression.withAnnotation(recordedMethodUses); + } push(expression.withSourceInformation(node.sourceInformation)); _registry.registerNativeMethod(target); return; diff --git a/pkg/compiler/test/record_use/data/js_interop.dart b/pkg/compiler/test/record_use/data/js_interop.dart new file mode 100644 index 00000000000..0fd0ad6a3b2 --- /dev/null +++ b/pkg/compiler/test/record_use/data/js_interop.dart @@ -0,0 +1,15 @@ +// 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 'dart:js_interop'; + +import 'package:meta/meta.dart' show RecordUse; + +void main() { + print(someExternalFunction(6)); +} + +@JS() +@RecordUse() +external int someExternalFunction(int k); diff --git a/pkg/compiler/test/record_use/data/js_interop.dart.json.expect b/pkg/compiler/test/record_use/data/js_interop.dart.json.expect new file mode 100644 index 00000000000..1108c1c4e38 --- /dev/null +++ b/pkg/compiler/test/record_use/data/js_interop.dart.json.expect @@ -0,0 +1,15 @@ +{ + "metadata": { + "comment": "Resources referenced by annotated resource identifiers", + "AppTag": "TBD", + "environment": { + "dart.web.assertions_enabled": "false", + "dart.tool.dart2js": "true", + "dart.tool.dart2js.minify": "false", + "dart.tool.dart2js.disable_rti_optimization": "false", + "dart.tool.dart2js.primitives:trust": "false", + "dart.tool.dart2js.types:trust": "false" + }, + "version": "0.4.0" + } +} \ No newline at end of file diff --git a/pkg/compiler/test/record_use/record_use_test.dart b/pkg/compiler/test/record_use/record_use_test.dart index 7a986d05bd3..a12786827b7 100644 --- a/pkg/compiler/test/record_use/record_use_test.dart +++ b/pkg/compiler/test/record_use/record_use_test.dart @@ -3,7 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import 'dart:convert'; -import 'dart:io' show File, Directory; +import 'dart:io' show Directory, File, Platform; import 'package:compiler/compiler_api.dart' as api show OutputType; import 'package:compiler/compiler_api.dart'; @@ -20,10 +20,12 @@ const List compilerOptions = [Flags.writeRecordedUses, Flags.testMode]; /// Run `dart --define=updateExpectations=true pkg/compiler/test/record_use/record_use_test.dart` /// to update. +/// Run `dart -DupdateExpectations=true pkg/vm/test/transformations/record_use_test.dart` +/// to update the shared expectations to the VM output. Future main() async { final vmTestCases = Directory('pkg/vm/testcases/transformations/record_use'); - final testFiles = vmTestCases - .listSync() + final jsTestCases = Directory.fromUri(Platform.script.resolve('data')); + final testFiles = [...jsTestCases.listSync(), ...vmTestCases.listSync()] .whereType() .where((file) => file.path.endsWith('.dart')) .map(