a63045d197
Since that stops `dart:_js_annotations` from building on dart2wasm, let's stop supporting that, too. This causes `package:js` to no longer work on dart2wasm, but none of the allowlisted packages use it any longer, so we can simply migrate tests off of it. Fixes: #56502 Fixes: #61550 Change-Id: I6a6a696438255ebf25a5a17131cdbd327ba81581 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/453645 Commit-Queue: Mayank Patke <fishythefish@google.com> Reviewed-by: Srujan Gaddam <srujzs@google.com> Reviewed-by: Paul Berry <paulberry@google.com> Reviewed-by: Nate Biggs <natebiggs@google.com>
545 lines
15 KiB
Dart
545 lines
15 KiB
Dart
// Copyright (c) 2022, 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.
|
|
|
|
// dart2wasmOptions=--extra-compiler-option=--enable-experimental-wasm-interop
|
|
|
|
import 'dart:js_interop';
|
|
import 'dart:js_interop_unsafe';
|
|
|
|
import 'package:expect/expect.dart';
|
|
|
|
@JS()
|
|
external void eval(String code);
|
|
|
|
typedef SumTwoPositionalFun = String Function(String a, String b);
|
|
typedef SumOnePositionalAndOneOptionalFun =
|
|
String Function(String a, [String? b]);
|
|
typedef SumTwoOptionalFun = String Function([String? a, String? b]);
|
|
typedef SumOnePositionalAndOneOptionalNonNullFun =
|
|
String Function(String a, [String b]);
|
|
typedef SumTwoOptionalNonNullFun = String Function([String a, String b]);
|
|
|
|
@JS()
|
|
@staticInterop
|
|
class DartFromJSCallbackHelper {
|
|
external factory DartFromJSCallbackHelper.factory(
|
|
JSFunction sumTwoPositional,
|
|
JSFunction sumOnePositionalOneOptional,
|
|
JSFunction sumTwoOptional,
|
|
JSFunction sumOnePositionalAndOneOptionalNonNull,
|
|
JSFunction sumTwoOptionalNonNull,
|
|
);
|
|
}
|
|
|
|
extension DartFromJSCallbackHelperMethods on DartFromJSCallbackHelper {
|
|
external String doSum1();
|
|
external String doSum2(String a, String b);
|
|
external String doSum3(JSFunction summer);
|
|
|
|
external String doSumOnePositionalAndOneOptionalA(String a);
|
|
external String doSumOnePositionalAndOneOptionalB(String a, String b);
|
|
external String doSumTwoOptionalA();
|
|
external String doSumTwoOptionalB(String a);
|
|
external String doSumTwoOptionalC(String a, String b);
|
|
|
|
external String doSumOnePositionalAndOneOptionalANonNull(String a);
|
|
external String doSumOnePositionalAndOneOptionalBNonNull(String a, String b);
|
|
external String doSumTwoOptionalANonNull();
|
|
external String doSumTwoOptionalBNonNull(String a);
|
|
external String doSumTwoOptionalCNonNull(String a, String b);
|
|
}
|
|
|
|
String sumTwoPositional(String a, String b) {
|
|
return a + b;
|
|
}
|
|
|
|
String sumOnePositionalAndOneOptional(String a, [String? b]) {
|
|
return a + (b ?? 'bar');
|
|
}
|
|
|
|
String sumTwoOptional([String? a, String? b]) {
|
|
return (a ?? 'foo') + (b ?? 'bar');
|
|
}
|
|
|
|
String sumOnePositionalAndOneOptionalNonNull(String a, [String b = 'bar']) {
|
|
return a + b;
|
|
}
|
|
|
|
String sumTwoOptionalNonNull([String a = 'foo', String b = 'bar']) {
|
|
return a + b;
|
|
}
|
|
|
|
void staticInteropCallbackTest() {
|
|
eval(r'''
|
|
globalThis.DartFromJSCallbackHelper = function(
|
|
sumTwoPositional, sumOnePositionalOneOptional, sumTwoOptional,
|
|
sumOnePositionalAndOneOptionalNonNull, sumTwoOptionalNonNull) {
|
|
this.a = 'hello ';
|
|
this.b = 'world!';
|
|
this.sum = null;
|
|
this.sumTwoPositional = sumTwoPositional;
|
|
this.sumOnePositionalOneOptional = sumOnePositionalOneOptional;
|
|
this.sumTwoOptional = sumTwoOptional;
|
|
this.sumOnePositionalAndOneOptionalNonNull = sumOnePositionalAndOneOptionalNonNull;
|
|
this.sumTwoOptionalNonNull = sumTwoOptionalNonNull;
|
|
this.doSum1 = () => {
|
|
return this.sumTwoPositional(this.a, this.b);
|
|
}
|
|
this.doSum2 = (a, b) => {
|
|
return this.sumTwoPositional(a, b);
|
|
}
|
|
this.doSum3 = (summer) => {
|
|
return summer(this.a, this.b);
|
|
}
|
|
this.doSumOnePositionalAndOneOptionalA = (a) => {
|
|
return sumOnePositionalOneOptional(a);
|
|
}
|
|
this.doSumOnePositionalAndOneOptionalB = (a, b) => {
|
|
return sumOnePositionalOneOptional(a, b);
|
|
}
|
|
this.doSumTwoOptionalA = () => {
|
|
return sumTwoOptional();
|
|
}
|
|
this.doSumTwoOptionalB = (a) => {
|
|
return sumTwoOptional(a);
|
|
}
|
|
this.doSumTwoOptionalC = (a, b) => {
|
|
return sumTwoOptional(a, b);
|
|
}
|
|
this.doSumOnePositionalAndOneOptionalANonNull = (a) => {
|
|
return sumOnePositionalAndOneOptionalNonNull(a);
|
|
}
|
|
this.doSumOnePositionalAndOneOptionalBNonNull = (a, b) => {
|
|
return sumOnePositionalAndOneOptionalNonNull(a, b);
|
|
}
|
|
this.doSumTwoOptionalANonNull = () => {
|
|
return sumTwoOptionalNonNull();
|
|
}
|
|
this.doSumTwoOptionalBNonNull = (a) => {
|
|
return sumTwoOptionalNonNull(a);
|
|
}
|
|
this.doSumTwoOptionalCNonNull = (a, b) => {
|
|
return sumTwoOptionalNonNull(a, b);
|
|
}
|
|
|
|
}
|
|
''');
|
|
|
|
final helper = DartFromJSCallbackHelper.factory(
|
|
sumTwoPositional.toJS,
|
|
sumOnePositionalAndOneOptional.toJS,
|
|
sumTwoOptional.toJS,
|
|
sumOnePositionalAndOneOptionalNonNull.toJS,
|
|
sumTwoOptionalNonNull.toJS,
|
|
);
|
|
|
|
Expect.equals('hello world!', helper.doSum1());
|
|
Expect.equals('foobar', helper.doSum2('foo', 'bar'));
|
|
Expect.equals(
|
|
'hello world!',
|
|
helper.doSum3(((String a, String b) => a + b).toJS),
|
|
);
|
|
|
|
Expect.equals('foobar', helper.doSumOnePositionalAndOneOptionalA('foo'));
|
|
Expect.equals(
|
|
'foobar',
|
|
helper.doSumOnePositionalAndOneOptionalB('foo', 'bar'),
|
|
);
|
|
Expect.equals('foobar', helper.doSumTwoOptionalA());
|
|
Expect.equals('foobar', helper.doSumTwoOptionalB('foo'));
|
|
Expect.equals('foobar', helper.doSumTwoOptionalC('foo', 'bar'));
|
|
|
|
Expect.equals(
|
|
'foobar',
|
|
helper.doSumOnePositionalAndOneOptionalANonNull('foo'),
|
|
);
|
|
Expect.equals(
|
|
'foobar',
|
|
helper.doSumOnePositionalAndOneOptionalBNonNull('foo', 'bar'),
|
|
);
|
|
Expect.equals('foobar', helper.doSumTwoOptionalANonNull());
|
|
Expect.equals('foobar', helper.doSumTwoOptionalBNonNull('foo'));
|
|
Expect.equals('foobar', helper.doSumTwoOptionalCNonNull('foo', 'bar'));
|
|
}
|
|
|
|
typedef NoArgsFun = String Function();
|
|
typedef OneArgFun = String Function(String arg);
|
|
typedef OnePositionalAndOneOptionalArgsFun =
|
|
String Function(String arg, [String arg2]);
|
|
typedef TwoOptionalArgsFun = String Function([String arg, String arg2]);
|
|
|
|
class TornOffClass {
|
|
String noArgs() {
|
|
return 'foo';
|
|
}
|
|
|
|
String oneArg(String arg) {
|
|
return arg;
|
|
}
|
|
|
|
String onePositionalAndOneOptionalArgs(String arg, [String arg2 = 'bar']) {
|
|
return arg + arg2;
|
|
}
|
|
|
|
String twoOptionalArgs([String arg = 'foo', String? arg2]) {
|
|
return arg + (arg2 ?? '');
|
|
}
|
|
}
|
|
|
|
typedef OneArgFunB = String Function(double arg);
|
|
typedef OnePositionalAndOneOptionalArgsFunB =
|
|
String Function(double arg, [String arg2]);
|
|
typedef TwoOptionalArgsFunB = String Function([double arg, String arg2]);
|
|
|
|
class GenericTornOffClass<T, V> {
|
|
String noArgs() {
|
|
return 'foo';
|
|
}
|
|
|
|
String oneArg(T arg) {
|
|
return '$arg';
|
|
}
|
|
|
|
String onePositionalAndOneOptionalArgs(T arg, [V? arg2]) {
|
|
return '$arg $arg2';
|
|
}
|
|
|
|
String twoOptionalArgs([T? arg, V? arg2]) {
|
|
return '$arg $arg2';
|
|
}
|
|
}
|
|
|
|
void unsafeInteropCallbackTest() {
|
|
eval(r'''
|
|
globalThis.doSum1 = function(summer) {
|
|
return summer('foo', 'bar');
|
|
}
|
|
globalThis.doSum2 = function(a, b) {
|
|
return globalThis.summer(a, b);
|
|
}
|
|
globalThis.doSumOnePositionalAndOneOptionalA = function(a) {
|
|
return summer(a);
|
|
}
|
|
globalThis.doSumOnePositionalAndOneOptionalB = function(a, b) {
|
|
return summer(a, b);
|
|
}
|
|
globalThis.doSumTwoOptionalA = function() {
|
|
return summer();
|
|
}
|
|
globalThis.doSumTwoOptionalB = function(a) {
|
|
return summer(a);
|
|
}
|
|
globalThis.doSumTwoOptionalC = function(a, b) {
|
|
return summer(a, b);
|
|
}
|
|
globalThis.doSumOnePositionalAndOneOptionalANonNull = function(a) {
|
|
return summer(a);
|
|
}
|
|
globalThis.doSumOnePositionalAndOneOptionalBNonNull = function(a, b) {
|
|
return summer(a, b);
|
|
}
|
|
globalThis.doSumTwoOptionalANonNull = function() {
|
|
return summer();
|
|
}
|
|
globalThis.doSumTwoOptionalBNonNull = function(a) {
|
|
return summer(a);
|
|
}
|
|
globalThis.doSumTwoOptionalCNonNull = function(a, b) {
|
|
return summer(a, b);
|
|
}
|
|
|
|
// tear off cases
|
|
globalThis.tearOffNoArgs = function (f) {
|
|
return f();
|
|
}
|
|
globalThis.tearOffOneArg = function (f) {
|
|
return f('foo');
|
|
}
|
|
globalThis.tearOffOnePositionalAndOneOptionalArgsA = function (f) {
|
|
return f('foo');
|
|
}
|
|
globalThis.tearOffOnePositionalAndOneOptionalArgsB = function (f) {
|
|
return f('foo', 'baz');
|
|
}
|
|
globalThis.tearOffTwoOptionalArgsA = function (f) {
|
|
return f('foo');
|
|
}
|
|
globalThis.tearOffTwoOptionalArgsB = function (f) {
|
|
return f('foo', 'baz');
|
|
}
|
|
|
|
// tear off generic class cases
|
|
globalThis.tearOffGenericNoArgs = function (f) {
|
|
return f();
|
|
}
|
|
globalThis.tearOffGenericOneArg = function (f) {
|
|
return f(1.0);
|
|
}
|
|
globalThis.tearOffGenericOnePositionalAndOneOptionalArgsA = function (f) {
|
|
return f(1.0);
|
|
}
|
|
globalThis.tearOffGenericOnePositionalAndOneOptionalArgsB = function (f) {
|
|
return f(1.0, 'baz');
|
|
}
|
|
globalThis.tearOffGenericTwoOptionalArgsA = function (f) {
|
|
return f(1.0);
|
|
}
|
|
globalThis.tearOffGenericTwoOptionalArgsB = function (f) {
|
|
return f(1.0, 'baz');
|
|
}
|
|
''');
|
|
|
|
// General
|
|
{
|
|
final interopCallback = ((String a, String b) => a + b).toJS;
|
|
Expect.equals(
|
|
'foobar',
|
|
globalContext.callMethod('doSum1'.toJS, interopCallback).toString(),
|
|
);
|
|
globalContext['summer'] = interopCallback;
|
|
Expect.equals(
|
|
'foobar',
|
|
globalContext
|
|
.callMethod('doSum2'.toJS, 'foo'.toJS, 'bar'.toJS)
|
|
.toString(),
|
|
);
|
|
final roundTripCallback = globalContext['summer'];
|
|
Expect.equals(
|
|
'foobar',
|
|
(roundTripCallback.dartify() as SumTwoPositionalFun)('foo', 'bar'),
|
|
);
|
|
}
|
|
|
|
// 1 nullable optional argument
|
|
{
|
|
final interopCallback = ((String a, [String? b]) => a + (b ?? 'bar')).toJS;
|
|
globalContext['summer'] = interopCallback;
|
|
Expect.equals(
|
|
'foobar',
|
|
globalContext
|
|
.callMethod('doSumOnePositionalAndOneOptionalA'.toJS, 'foo'.toJS)
|
|
.toString(),
|
|
);
|
|
Expect.equals(
|
|
'foobar',
|
|
globalContext
|
|
.callMethod(
|
|
'doSumOnePositionalAndOneOptionalB'.toJS,
|
|
'foo'.toJS,
|
|
'bar'.toJS,
|
|
)
|
|
.toString(),
|
|
);
|
|
}
|
|
|
|
// All nullable optional arguments
|
|
{
|
|
final interopCallback =
|
|
(([String? a, String? b]) => (a ?? 'foo') + (b ?? 'bar')).toJS;
|
|
globalContext['summer'] = interopCallback;
|
|
Expect.equals(
|
|
'foobar',
|
|
globalContext.callMethod('doSumTwoOptionalA'.toJS).toString(),
|
|
);
|
|
Expect.equals(
|
|
'foobar',
|
|
globalContext.callMethod('doSumTwoOptionalB'.toJS, 'foo'.toJS).toString(),
|
|
);
|
|
Expect.equals(
|
|
'foobar',
|
|
globalContext
|
|
.callMethod('doSumTwoOptionalC'.toJS, 'foo'.toJS, 'bar'.toJS)
|
|
.toString(),
|
|
);
|
|
}
|
|
|
|
// 1 non-nullable optional argument
|
|
{
|
|
final interopCallback = ((String a, [String b = 'bar']) => a + b).toJS;
|
|
globalContext['summer'] = interopCallback;
|
|
Expect.equals(
|
|
'foobar',
|
|
globalContext
|
|
.callMethod('doSumOnePositionalAndOneOptionalA'.toJS, 'foo'.toJS)
|
|
.toString(),
|
|
);
|
|
Expect.equals(
|
|
'foobar',
|
|
globalContext
|
|
.callMethod(
|
|
'doSumOnePositionalAndOneOptionalB'.toJS,
|
|
'foo'.toJS,
|
|
'bar'.toJS,
|
|
)
|
|
.toString(),
|
|
);
|
|
}
|
|
|
|
// All non-nullable optional arguments
|
|
{
|
|
final interopCallback =
|
|
(([String a = 'foo', String b = 'bar']) => a + b).toJS;
|
|
globalContext['summer'] = interopCallback;
|
|
Expect.equals(
|
|
'foobar',
|
|
globalContext.callMethod('doSumTwoOptionalA'.toJS).toString(),
|
|
);
|
|
Expect.equals(
|
|
'foobar',
|
|
globalContext.callMethod('doSumTwoOptionalB'.toJS, 'foo'.toJS).toString(),
|
|
);
|
|
Expect.equals(
|
|
'foobar',
|
|
globalContext
|
|
.callMethod('doSumTwoOptionalC'.toJS, 'foo'.toJS, 'bar'.toJS)
|
|
.toString(),
|
|
);
|
|
}
|
|
|
|
// Tear off cases
|
|
// No args.
|
|
{
|
|
final t = TornOffClass();
|
|
final interopCallback = t.noArgs.toJS;
|
|
Expect.equals(
|
|
'foo'.toJS,
|
|
globalContext.callMethod('tearOffNoArgs'.toJS, interopCallback),
|
|
);
|
|
}
|
|
|
|
// One arg.
|
|
{
|
|
final t = TornOffClass();
|
|
final interopCallback = t.oneArg.toJS;
|
|
Expect.equals(
|
|
'foo'.toJS,
|
|
globalContext.callMethod('tearOffOneArg'.toJS, interopCallback),
|
|
);
|
|
}
|
|
|
|
// One positional and one optional case A.
|
|
{
|
|
final t = TornOffClass();
|
|
final interopCallback = t.onePositionalAndOneOptionalArgs.toJS;
|
|
Expect.equals(
|
|
'foobar'.toJS,
|
|
globalContext.callMethod(
|
|
'tearOffOnePositionalAndOneOptionalArgsA'.toJS,
|
|
interopCallback,
|
|
),
|
|
);
|
|
}
|
|
|
|
// One positional and one optional case B.
|
|
{
|
|
final t = TornOffClass();
|
|
final interopCallback = t.onePositionalAndOneOptionalArgs.toJS;
|
|
Expect.equals(
|
|
'foobaz'.toJS,
|
|
globalContext.callMethod(
|
|
'tearOffOnePositionalAndOneOptionalArgsB'.toJS,
|
|
interopCallback,
|
|
),
|
|
);
|
|
}
|
|
|
|
// Two optional case A.
|
|
{
|
|
final t = TornOffClass();
|
|
final interopCallback = t.twoOptionalArgs.toJS;
|
|
Expect.equals(
|
|
'foo'.toJS,
|
|
globalContext.callMethod('tearOffTwoOptionalArgsA'.toJS, interopCallback),
|
|
);
|
|
}
|
|
|
|
// Two optional case B.
|
|
{
|
|
final t = TornOffClass();
|
|
final interopCallback = t.twoOptionalArgs.toJS;
|
|
Expect.equals(
|
|
'foobaz'.toJS,
|
|
globalContext.callMethod('tearOffTwoOptionalArgsB'.toJS, interopCallback),
|
|
);
|
|
}
|
|
|
|
// Tearoffs of generic classes.
|
|
// No args.
|
|
{
|
|
final t = GenericTornOffClass<double, String>();
|
|
final interopCallback = t.noArgs.toJS;
|
|
Expect.equals(
|
|
'foo'.toJS,
|
|
globalContext.callMethod('tearOffGenericNoArgs'.toJS, interopCallback),
|
|
);
|
|
}
|
|
|
|
// One arg.
|
|
{
|
|
final t = GenericTornOffClass<double, String>();
|
|
final interopCallback = t.oneArg.toJS;
|
|
Expect.equals(
|
|
'1.0'.toJS,
|
|
globalContext.callMethod('tearOffGenericOneArg'.toJS, interopCallback),
|
|
);
|
|
}
|
|
|
|
// One positional and one optional case A.
|
|
{
|
|
final t = GenericTornOffClass<double, String>();
|
|
final interopCallback = t.onePositionalAndOneOptionalArgs.toJS;
|
|
Expect.equals(
|
|
'1.0 null'.toJS,
|
|
globalContext.callMethod(
|
|
'tearOffGenericOnePositionalAndOneOptionalArgsA'.toJS,
|
|
interopCallback,
|
|
),
|
|
);
|
|
}
|
|
|
|
// One positional and one optional case B.
|
|
{
|
|
final t = GenericTornOffClass<double, String>();
|
|
final interopCallback = t.onePositionalAndOneOptionalArgs.toJS;
|
|
Expect.equals(
|
|
'1.0 baz'.toJS,
|
|
globalContext.callMethod(
|
|
'tearOffGenericOnePositionalAndOneOptionalArgsB'.toJS,
|
|
interopCallback,
|
|
),
|
|
);
|
|
}
|
|
|
|
// Two optional case A.
|
|
{
|
|
final t = GenericTornOffClass<double, String>();
|
|
final interopCallback = t.twoOptionalArgs.toJS;
|
|
Expect.equals(
|
|
'1.0 null'.toJS,
|
|
globalContext.callMethod(
|
|
'tearOffGenericTwoOptionalArgsA'.toJS,
|
|
interopCallback,
|
|
),
|
|
);
|
|
}
|
|
|
|
// Two optional case B.
|
|
{
|
|
final t = GenericTornOffClass<double, String>();
|
|
final interopCallback = t.twoOptionalArgs.toJS;
|
|
Expect.equals(
|
|
'1.0 baz'.toJS,
|
|
globalContext.callMethod(
|
|
'tearOffGenericTwoOptionalArgsB'.toJS,
|
|
interopCallback,
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
void main() {
|
|
staticInteropCallbackTest();
|
|
unsafeInteropCallbackTest();
|
|
}
|