Skip to content

Commit add2f41

Browse files
nshahanCommit Queue
authored and
Commit Queue
committed
[web] Add static js interop .call() tests
These tests should help: - avoid regressions in the existing behavior - highlight incremental improvements towards implementing the desired behavior (with corresponding changes to the expectations) - identify the differences between the JavaScript and wasm compilers Change-Id: Ie95233868a13b7ffffc2688ab7c973dcd14ed721 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/359246 Reviewed-by: Srujan Gaddam <[email protected]> Reviewed-by: Sigmund Cherem <[email protected]> Commit-Queue: Nicholas Shahan <[email protected]> Reviewed-by: Bob Nystrom <[email protected]>
1 parent c5f876b commit add2f41

File tree

4 files changed

+466
-0
lines changed

4 files changed

+466
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
/// WARNING
6+
///
7+
/// Not all of the expectations in this test match the language specification.
8+
///
9+
/// This is part of a set of tests covering "callable objects". Please consider
10+
/// them all together when making changes:
11+
///
12+
/// ```
13+
/// tests/lib/js/static_interop_test/call_getter_test.dart
14+
/// tests/lib/js/static_interop_test/call_method_test.dart
15+
/// ```
16+
///
17+
/// This test was created with expectations that match the current behavior to
18+
/// make it more clear when something changes and when the results in the web
19+
/// compilers differ.
20+
///
21+
/// If your change causes an expectation to fail you should decide if the
22+
/// new result is desireable and update the expectation accordingly.
23+
24+
import 'dart:js_interop';
25+
26+
import 'package:expect/expect.dart';
27+
28+
import 'call_utils.dart';
29+
30+
@JS('jsFunction')
31+
external JSFunction get jsFunctionAsJSFunction;
32+
33+
@JS('jsObject')
34+
external JSFunction get jsObjectAsJSFunction;
35+
36+
@JS('jsClass')
37+
external JSFunction get jsClassAsJSFunction;
38+
39+
extension on JSFunction {
40+
@JS('call')
41+
external String _call(JSAny? self, String s);
42+
43+
String Function(String) get call => (String s) => _call(globalContext, s);
44+
}
45+
46+
extension type ExtOnJSObject._(JSObject _) {
47+
@JS('call')
48+
external String _call(String s);
49+
50+
String Function(String) get call => (String s) => _call(s);
51+
}
52+
53+
@JS('jsFunction')
54+
external ExtOnJSObject get jsFunctionAsExtOnJSObject;
55+
56+
@JS('jsObject')
57+
external ExtOnJSObject get jsObjectAsExtOnJSObject;
58+
59+
@JS('jsClass')
60+
external ExtOnJSObject get jsClassAsExtOnJSObject;
61+
62+
extension type ExtOnJSObject2._(JSObject _) {
63+
external JSFunction get call;
64+
}
65+
66+
@JS('jsFunction')
67+
external ExtOnJSObject2 get jsFunctionAsExtOnJSObject2;
68+
69+
@JS('jsObject')
70+
external ExtOnJSObject2 get jsObjectAsExtOnJSObject2;
71+
72+
@JS('jsClass')
73+
external ExtOnJSObject2 get jsClassAsExtOnJSObject2;
74+
75+
extension type ExtOnJSFunction._(JSFunction _) {
76+
external JSFunction get call;
77+
}
78+
79+
@JS('jsFunction')
80+
external ExtOnJSFunction get jsFunctionAsExtOnJSFunction;
81+
82+
@JS('jsObject')
83+
external ExtOnJSFunction get jsObjectAsExtOnJSFunction;
84+
85+
@JS('jsClass')
86+
external ExtOnJSFunction get jsClassAsExtOnJSFunction;
87+
88+
void main() {
89+
injectJS();
90+
testJSFunction();
91+
testExtOnJSObject();
92+
testExtOnJSObject2();
93+
testExtOnJSFunction();
94+
testAsDynamic();
95+
}
96+
97+
void testJSFunction() {
98+
var obj = jsFunctionAsJSFunction;
99+
Expect.equals('C',
100+
(obj.callAsFunction(globalContext, 'Cello'.toJS) as JSString).toDart);
101+
Expect.equals('C', obj.call('Cello'));
102+
Expect.equals('C', (obj.call)('Cello'));
103+
104+
if (dart2wasm) {
105+
obj = jsObjectAsJSFunction;
106+
Expect.throws(() => obj.callAsFunction(globalContext, 'Cello'.toJS));
107+
Expect.throws(() => obj.call('Cello'));
108+
Expect.throws(() => (obj.call)('Cello'));
109+
} else {
110+
Expect.throwsTypeError(() => jsObjectAsJSFunction);
111+
}
112+
113+
if (dart2wasm) {
114+
obj = jsClassAsJSFunction;
115+
Expect.throws(() => obj.callAsFunction(globalContext, 'Cello'.toJS));
116+
Expect.throws(() => obj.call('Cello'));
117+
Expect.throws(() => (obj.call)('Cello'));
118+
} else {
119+
Expect.throwsTypeError(() => jsClassAsJSFunction);
120+
}
121+
}
122+
123+
void testExtOnJSObject() {
124+
var obj = jsFunctionAsExtOnJSObject;
125+
Expect.throws(
126+
() => obj.call('Cello'), dart2wasm ? null : jsArgIsNotStringCheck);
127+
Expect.throws(
128+
() => (obj.call)('Cello'), dart2wasm ? null : jsArgIsNotStringCheck);
129+
130+
obj = jsObjectAsExtOnJSObject;
131+
Expect.equals('C', obj.call('Cello'));
132+
Expect.equals('C', (obj.call)('Cello'));
133+
134+
obj = jsClassAsExtOnJSObject;
135+
Expect.equals('C', obj.call('Cello'));
136+
Expect.equals('C', (obj.call)('Cello'));
137+
}
138+
139+
void testExtOnJSObject2() {
140+
var obj = jsFunctionAsExtOnJSObject2;
141+
Expect.throws(() =>
142+
obj.call.callAsFunction(globalContext, globalContext, 'Cello'.toJS));
143+
144+
obj = jsObjectAsExtOnJSObject2;
145+
Expect.equals(
146+
'C',
147+
(obj.call.callAsFunction(globalContext, 'Cello'.toJS) as JSString)
148+
.toDart);
149+
150+
obj = jsClassAsExtOnJSObject2;
151+
Expect.equals(
152+
'C',
153+
(obj.call.callAsFunction(globalContext, 'Cello'.toJS) as JSString)
154+
.toDart);
155+
}
156+
157+
void testExtOnJSFunction() {
158+
var obj = jsFunctionAsExtOnJSFunction;
159+
Expect.throws(() => obj.call.callAsFunction(globalContext, 'Cello'.toJS));
160+
161+
if (dart2wasm) {
162+
obj = jsObjectAsExtOnJSFunction;
163+
Expect.equals(
164+
'C',
165+
(obj.call.callAsFunction(globalContext, 'Cello'.toJS) as JSString)
166+
.toDart);
167+
} else {
168+
Expect.throwsTypeError(() => jsObjectAsExtOnJSFunction);
169+
}
170+
171+
if (dart2wasm) {
172+
obj = jsClassAsExtOnJSFunction;
173+
Expect.equals(
174+
'C',
175+
(obj.call.callAsFunction(globalContext, 'Cello'.toJS) as JSString)
176+
.toDart);
177+
} else {
178+
Expect.throwsTypeError(() => jsClassAsExtOnJSFunction);
179+
}
180+
}
181+
182+
testAsDynamic() {
183+
dynamic d = confuse(jsFunctionAsJSFunction);
184+
if (dart2wasm) {
185+
Expect.throwsNoSuchMethodError(() => d.call('Fosse'));
186+
} else {
187+
Expect.equals('F', d.call('Fosse'));
188+
}
189+
if (ddc) {
190+
Expect.equals('F', (d.call)('Fosse'));
191+
} else {
192+
Expect.throwsNoSuchMethodError(() => (d.call)('Fosse'));
193+
}
194+
if (dart2wasm) {
195+
Expect.throwsNoSuchMethodError(() => d('Fosse'));
196+
} else {
197+
Expect.equals('F', d('Fosse'));
198+
}
199+
200+
d = confuse(jsObjectAsExtOnJSObject);
201+
Expect.throwsNoSuchMethodError(() => d.call('Fosse'));
202+
if (ddc) {
203+
Expect.equals('F', (d.call)('Fosse'));
204+
} else {
205+
Expect.throwsNoSuchMethodError(() => (d.call)('Fosse'));
206+
}
207+
Expect.throwsNoSuchMethodError(() => d('Fosse'));
208+
209+
d = confuse(jsClassAsExtOnJSObject);
210+
Expect.throwsNoSuchMethodError(() => d.call('Fosse'));
211+
if (ddc) {
212+
Expect.throws(() => (d.call)('Fosse'), jsThisIsNullCheck);
213+
} else {
214+
Expect.throwsNoSuchMethodError(() => (d.call)('Fosse'));
215+
}
216+
Expect.throwsNoSuchMethodError(() => d('Fosse'));
217+
}

0 commit comments

Comments
 (0)