[dart2js] external functions record_use

Closes: https://github.com/dart-lang/native/issues/2960

Change-Id: I3d62cb9bee6d06f799ee41bc283dce0dacb893cd
Cq-Include-Trybots: luci.dart.try:pkg-linux-debug-try,pkg-linux-release-arm64-try,pkg-linux-release-try,pkg-mac-release-arm64-try,pkg-mac-release-try,pkg-win-release-arm64-try,pkg-win-release-try,dart2js-linux-chrome-try,dart2js-unit-linux-x64-release-try,dart2wasm-linux-jscm-chrome-try,dart2wasm-linux-optimized-jsc-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/473480
Commit-Queue: Daco Harkes <dacoharkes@google.com>
Reviewed-by: Nate Biggs <natebiggs@google.com>
This commit is contained in:
Daco Harkes
2026-01-16 00:27:49 -08:00
committed by Commit Queue
parent e37343fa6d
commit 9e4bb73f8e
4 changed files with 50 additions and 3 deletions
+15
View File
@@ -2677,6 +2677,15 @@ class SsaCodeGenerator implements HVisitor<void>, 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<void>, 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<void>, 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;
@@ -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);
@@ -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"
}
}
@@ -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<String> 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<void> 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<File>()
.where((file) => file.path.endsWith('.dart'))
.map(