Update CFE expectations and fix top-level external members

Since we lower @staticInterop members differently, CFE expectations are
updated. A previous patchset updated tests to account for changes in
top-level external members, but those changes are now non-breaking.
This CL still keeps some of those fixes to tests since they are more
sound and correct:

- Debugger tests to allowInterop a function that wasn't caught before,
as DDC only adds checks for arguments whose static type is a Function,
whereas js_util does a runtime is check to determine if the argument is
a Function
- Interop tests that typed top-level externals unsoundly
- Interop tests that used tear-offs of top-level external methods
instead of getters

Change-Id: I46a5a1316db1dba38691efece075f9c34ac4b4e0
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/277660
Reviewed-by: Sigmund Cherem <sigmund@google.com>
This commit is contained in:
Srujan Gaddam 2023-01-16 22:31:33 +00:00 committed by Commit Queue
parent 9c8051b3ee
commit f04331891f
16 changed files with 69 additions and 31 deletions

View file

@ -14,13 +14,15 @@ library static_interop /*isNonNullableByDefault*/;
import self as sta;
import "package:js/js.dart" as js;
import "dart:core" as core;
import "dart:js_util" as js_;
import "package:js/js.dart";
@#C4
@#C5
class StaticJSClass extends core::Object {
external static factory •() → sta::StaticJSClass;
static factory •() → sta::StaticJSClass
return js_::_callConstructorUnchecked0<sta::StaticJSClass>(js_::_getPropertyTrustType<core::Object>(js_::globalThis, "JSClass"));
static method _#new#tearOff() → sta::StaticJSClass
return sta::StaticJSClass::•();
static factory factory() → sta::StaticJSClass {

View file

@ -14,13 +14,15 @@ library static_interop /*isNonNullableByDefault*/;
import self as sta;
import "package:js/js.dart" as js;
import "dart:core" as core;
import "dart:js_util" as js_;
import "package:js/js.dart";
@#C4
@#C5
class StaticJSClass extends core::Object {
external static factory •() → sta::StaticJSClass;
static factory •() → sta::StaticJSClass
return js_::_callConstructorUnchecked0<sta::StaticJSClass>(js_::_getPropertyTrustType<core::Object>(js_::globalThis, "JSClass"));
static method _#new#tearOff() → sta::StaticJSClass
return sta::StaticJSClass::•();
static factory factory() → sta::StaticJSClass {

View file

@ -14,13 +14,15 @@ library static_interop /*isNonNullableByDefault*/;
import self as sta;
import "package:js/js.dart" as js;
import "dart:core" as core;
import "dart:js_util" as js_;
import "package:js/js.dart";
@#C4
@#C5
class StaticJSClass extends core::Object {
external static factory •() → sta::StaticJSClass;
static factory •() → sta::StaticJSClass
return js_::_callConstructorUnchecked0<sta::StaticJSClass>(js_::_getPropertyTrustType<core::Object>(js_::globalThis, "JSClass"));
static method _#new#tearOff() → sta::StaticJSClass
return sta::StaticJSClass::•();
static factory factory() → sta::StaticJSClass {

View file

@ -11,13 +11,15 @@ library static_interop /*isNonNullableByDefault*/;
import self as self2;
import "package:js/js.dart" as js;
import "dart:core" as core;
import "dart:js_util" as js_;
import "package:js/js.dart";
@#C4
@#C5
class StaticJSClass extends core::Object {
external static factory •() → self2::StaticJSClass;
static factory •() → self2::StaticJSClass
return js_::_callConstructorUnchecked0<self2::StaticJSClass>(js_::_getPropertyTrustType<core::Object>(js_::globalThis, "JSClass"));
static method _#new#tearOff() → self2::StaticJSClass
return self2::StaticJSClass::•();
static factory factory() → self2::StaticJSClass

View file

@ -14,13 +14,15 @@ library static_interop /*isNonNullableByDefault*/;
import self as sta;
import "package:js/js.dart" as js;
import "dart:core" as core;
import "dart:js_util" as js_;
import "package:js/js.dart";
@#C4
@#C5
class StaticJSClass extends core::Object {
external static factory •() → sta::StaticJSClass;
static factory •() → sta::StaticJSClass
return js_::_callConstructorUnchecked0<sta::StaticJSClass>(js_::_getPropertyTrustType<core::Object>(js_::globalThis, "JSClass"));
static method _#new#tearOff() → sta::StaticJSClass
return sta::StaticJSClass::•();
static factory factory() → sta::StaticJSClass {

View file

@ -53,7 +53,8 @@ library static_interop from "org-dartlang-test:///lib2.dart" as sta {
@#C5
@#C2
class StaticJSClass extends dart.core::Object {
external static factory •() → sta::StaticJSClass;
static factory •() → sta::StaticJSClass
return dart.js_util::_callConstructorUnchecked0<sta::StaticJSClass>(dart.js_util::_getPropertyTrustType<dart.core::Object>(dart.js_util::globalThis, "JSClass"));
static method _#new#tearOff() → sta::StaticJSClass
return sta::StaticJSClass::•();
static factory factory() → sta::StaticJSClass {

View file

@ -53,7 +53,8 @@ library static_interop from "org-dartlang-test:///lib2.dart" as sta {
@#C5
@#C2
class StaticJSClass extends dart.core::Object {
external static factory •() → sta::StaticJSClass;
static factory •() → sta::StaticJSClass
return dart.js_util::_callConstructorUnchecked0<sta::StaticJSClass>(dart.js_util::_getPropertyTrustType<dart.core::Object>(dart.js_util::globalThis, "JSClass"));
static method _#new#tearOff() → sta::StaticJSClass
return sta::StaticJSClass::•();
static factory factory() → sta::StaticJSClass {

View file

@ -84,6 +84,7 @@ replacer(String key, value) {
String? format(value) {
// Avoid double-escaping strings.
if (value is String) return value;
if (value is Function) value = allowInterop(value);
return stringify(value, allowInterop(replacer), 4);
}
@ -214,7 +215,10 @@ window.ExampleJSClass = function ExampleJSClass(x) {
addNestedFormatterGoldens('Iterable', iterable);
var s = new Set()..add("foo")..add(42)..add(true);
var s = new Set()
..add("foo")
..add(42)
..add(true);
addNestedFormatterGoldens('Set', s);
});

View file

@ -23,17 +23,26 @@ class Console {
@JS('console')
external Console get console;
@JS('console.log')
external Function get _log;
@JS('console.log')
external void log(String s);
String dartStaticMethod() => 'hello';
@JS('jsStaticVariable')
external set _jsStaticVariable(Function f);
external Function? get _jsStaticVariable;
@JS('jsStaticVariable')
external set _jsStaticVariable(Function? f);
@JS('jsStaticVariable')
external void jsStaticVariable(String s);
@JS('jsStaticFunction')
external Function get _jsStaticFunction;
@JS('jsStaticFunction')
external set _jsStaticFunction(Function f);
@ -66,14 +75,14 @@ void main() {
Function(String) jsFunc = helper.JS('', '(x) => {}');
Expect.equals(dart.assertInterop(jsFunc), jsFunc);
Expect.equals(dart.assertInterop(log), log);
Expect.equals(dart.assertInterop(_log), _log);
Expect.equals(dart.assertInterop(console.log), console.log);
Expect.throws(() => dart.assertInterop(dartStaticMethod));
Expect.isNull(jsStaticVariable);
Expect.isNull(_jsStaticVariable);
_jsStaticVariable = jsFunc;
Expect.isNotNull(jsStaticVariable);
Expect.equals(dart.assertInterop(jsStaticVariable), jsStaticVariable);
Expect.isNotNull(_jsStaticVariable);
Expect.equals(dart.assertInterop(_jsStaticVariable), _jsStaticVariable);
final dynamic wrappedDartStaticMethod = allowInterop(dartStaticMethod);
@ -293,7 +302,7 @@ void main() {
// Stored Function typed getter
method = someClass.jsFunctionFieldGetter;
// We lose safety after calling a getter that returns a function, which takes
// a function as an argument. Since this can be modeled with a method, instead
// a function as an argument. Since this can be modeled with a method, isntead
// of a getter returning a function, we don't expect this is a pattern likely
// to show up in real code.
//Expect.throws(() {

View file

@ -86,6 +86,7 @@ replacer(String key, value) {
String format(value) {
// Avoid double-escaping strings.
if (value is String) return value;
if (value is Function) value = allowInterop(value as Function);
return stringify(value, allowInterop(replacer), 4);
}
@ -216,7 +217,10 @@ window.ExampleJSClass = function ExampleJSClass(x) {
addNestedFormatterGoldens('Iterable', iterable);
var s = new Set()..add("foo")..add(42)..add(true);
var s = new Set()
..add("foo")
..add(42)
..add(true);
addNestedFormatterGoldens('Set', s);
});

View file

@ -23,17 +23,26 @@ class Console {
@JS('console')
external Console get console;
@JS('console.log')
external Function get _log;
@JS('console.log')
external void log(String s);
String dartStaticMethod() => 'hello';
@JS('jsStaticVariable')
external Function get _jsStaticVariable;
@JS('jsStaticVariable')
external set _jsStaticVariable(Function f);
@JS('jsStaticVariable')
external void jsStaticVariable(String s);
@JS('jsStaticFunction')
external Function get _jsStaticFunction;
@JS('jsStaticFunction')
external set _jsStaticFunction(Function f);
@ -66,14 +75,14 @@ void main() {
Function(String) jsFunc = helper.JS('', '(x) => {}');
Expect.equals(dart.assertInterop(jsFunc), jsFunc);
Expect.equals(dart.assertInterop(log), log);
Expect.equals(dart.assertInterop(_log), _log);
Expect.equals(dart.assertInterop(console.log), console.log);
Expect.throws(() => dart.assertInterop(dartStaticMethod));
Expect.isNull(jsStaticVariable);
Expect.isNull(_jsStaticVariable);
_jsStaticVariable = jsFunc;
Expect.isNotNull(jsStaticVariable);
Expect.equals(dart.assertInterop(jsStaticVariable), jsStaticVariable);
Expect.isNotNull(_jsStaticVariable);
Expect.equals(dart.assertInterop(_jsStaticVariable), _jsStaticVariable);
final dynamic wrappedDartStaticMethod = allowInterop(dartStaticMethod);
@ -237,7 +246,7 @@ void main() {
// Stored Function typed getter
method = someClass.jsFunctionFieldGetter;
// We lose safety after calling a getter that returns a function, which takes
// a function as an argument. Since this can be modeled with a method, instead
// a function as an argument. Since this can be modeled with a method, isntead
// of a getter returning a function, we don't expect this is a pattern likely
// to show up in real code.
//Expect.throws(() {

View file

@ -71,7 +71,7 @@ _injectJs() {
getA: function() { return this.a;}
};
var selection = ["a", "b", "c", foo, bar];
var list = ["a", "b", "c", foo, bar];
function returnNumArgs() { return arguments.length; };
function returnLastArg() { return arguments[arguments.length-1]; };
@ -172,7 +172,7 @@ class Bar {
external Foo get foo;
external Foob get foob;
external Bar get bar;
external Selection get selection;
external Object get list;
addWithDefault(a, [b = 100]) => a + b;
@ -431,7 +431,7 @@ main() {
expect(dartObject is Foo, isFalse);
expect(dartObject is ExampleLiteral, isFalse);
expect(selection is List, isTrue);
expect(list is List, isTrue);
// We do know at runtime whether something is a JsArray or not.
expect(foo is List, isFalse);
@ -439,7 +439,7 @@ main() {
test('dart interfaces', () {
expect(foo is Function, isFalse);
expect(selection is List, isTrue);
expect(list is List, isTrue);
});
});

View file

@ -23,7 +23,7 @@ _injectJs() {
}
@JS("window.foo")
external List<Function> get foo;
external List<dynamic> get foo;
main() {
_injectJs();

View file

@ -15,7 +15,7 @@ import 'package:expect/minitest.dart';
external void eval(String code);
@JS()
external Object get undefinedObject;
external Object? get undefinedObject;
@JS()
class Foo {

View file

@ -73,7 +73,7 @@ _injectJs() {
getA: function() { return this.a;}
};
var selection = ["a", "b", "c", foo, bar];
var list = ["a", "b", "c", foo, bar];
function returnNumArgs() { return arguments.length; };
function returnLastArg() { return arguments[arguments.length-1]; };
@ -174,7 +174,7 @@ class Bar {
external Foo get foo;
external Foob get foob;
external Bar get bar;
external Selection get selection;
external Object get list;
addWithDefault(a, [b = 100]) => a + b;
@ -433,7 +433,7 @@ main() {
expect(dartObject is Foo, isFalse);
expect(dartObject is ExampleLiteral, isFalse);
expect(selection is List, isTrue);
expect(list is List, isTrue);
// We do know at runtime whether something is a JsArray or not.
expect(foo is List, isFalse);
@ -441,7 +441,7 @@ main() {
test('dart interfaces', () {
expect(foo is Function, isFalse);
expect(selection is List, isTrue);
expect(list is List, isTrue);
});
});

View file

@ -25,7 +25,7 @@ _injectJs() {
}
@JS("window.foo")
external List<Function> get foo;
external List<dynamic> get foo;
main() {
_injectJs();