[pkg:js] Add proto argument to createStaticInteropMock
Adds optional argument proto to allow users to pass instanceof/is
checks with the generated forwarding mock.
Change-Id: If2dba386fb0e66cbe738105e58d9e5ec1f02d02a
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/257162
Commit-Queue: Srujan Gaddam <srujzs@google.com>
Reviewed-by: Riley Porter <rileyporter@google.com>
diff --git a/pkg/_js_interop_checks/lib/src/transformations/static_interop_mock_creator.dart b/pkg/_js_interop_checks/lib/src/transformations/static_interop_mock_creator.dart
index e80ee64..d88e799 100644
--- a/pkg/_js_interop_checks/lib/src/transformations/static_interop_mock_creator.dart
+++ b/pkg/_js_interop_checks/lib/src/transformations/static_interop_mock_creator.dart
@@ -314,7 +314,8 @@
Map<ExtensionMemberDescriptor, Class> descriptorToClass,
Map<String, Member> dartMemberMap) {
var block = <Statement>[];
- assert(node.arguments.positional.length == 1);
+ var argsLength = node.arguments.positional.length;
+ assert(argsLength == 1 || argsLength == 2);
var interopType = node.arguments.types[0];
var dartType = node.arguments.types[1];
@@ -330,22 +331,25 @@
Arguments([StaticGet(_globalThis), StringLiteral('Object')],
types: [_objectType]));
- // Get a fresh object literal.
- // TODO(srujzs): Add prototype option for instance checks.
- StaticInvocation getLiteral() {
+ // Get a fresh object literal, using the proto to create it if one was
+ // given.
+ StaticInvocation getLiteral([Expression? proto]) {
return StaticInvocation(
_callMethod,
Arguments([
getObjectProperty(),
StringLiteral('create'),
- ListLiteral([NullLiteral()]),
+ ListLiteral([proto ?? NullLiteral()]),
], types: [
_objectType
]));
}
var jsMock = VariableDeclaration('#jsMock',
- initializer: AsExpression(getLiteral(), interopType), type: interopType)
+ initializer: AsExpression(
+ getLiteral(argsLength == 2 ? node.arguments.positional[1] : null),
+ interopType),
+ type: interopType)
..fileOffset = node.fileOffset
..parent = node.parent;
block.add(jsMock);
diff --git a/sdk/lib/js_util/js_util.dart b/sdk/lib/js_util/js_util.dart
index d3a4510..c233e9b 100644
--- a/sdk/lib/js_util/js_util.dart
+++ b/sdk/lib/js_util/js_util.dart
@@ -166,6 +166,10 @@
/// U that implements the external extension members of T, creates a forwarding
/// mock.
///
+/// Optionally, you may provide a JS prototype object e.g. the JS value
+/// `Window.prototype` using [proto]. This allows instanceof and is checks with
+/// `@Native` types to pass with the returned forwarding mock.
+///
/// When external extension members are called, they will forward to the
/// corresponding implementing member in [dartMock]. If U does not implement all
/// the external extension members of T, or if U does not properly override
@@ -194,4 +198,4 @@
/// TODO(srujzs): Add more detail on how inherited extension members need to be
/// implemented, as well as how conflicts are resolved (if they are resolvable).
/// The semantics here tries to conform to the view type specification.
-external T createStaticInteropMock<T, U>(U dartMock);
+external T createStaticInteropMock<T, U>(U dartMock, [Object? proto = null]);
diff --git a/tests/lib/js/static_interop_test/mock/functional_test.dart b/tests/lib/js/static_interop_test/mock/functional_test.dart
index f44f0cb..a43df9a 100644
--- a/tests/lib/js/static_interop_test/mock/functional_test.dart
+++ b/tests/lib/js/static_interop_test/mock/functional_test.dart
@@ -2,135 +2,8 @@
// 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.
-// Test basic functionality of `createStaticInteropMock`. Basic methods, fields
-// (final and not), getters, and setters are tested along with potential
-// renames.
-
-import 'package:expect/minitest.dart';
-import 'package:js/js.dart';
-import 'package:js/js_util.dart';
-
-@JS()
-@staticInterop
-class Methods {}
-
-extension on Methods {
- external int add(int a, int b);
- // Sanity-check that non-externals are unaffected.
- int nonExternal() => 0;
- @JS('_rename')
- external int rename();
- external int optionalAdd(int a, int b, [int c = 0, int? d]);
-}
-
-class MethodsDart {
- int add(int a, int b) => a + b;
- int nonExternal() => 1;
- int rename() => 1;
- int optionalAdd(int a, int b, [int? c, int? d]) =>
- a + b + (c ?? 0) + (d ?? 0);
-}
-
-@JS()
-@staticInterop
-class Fields {}
-
-extension on Fields {
- external int field;
- external final int finalField;
- @JS('_renamedField')
- external int renamedField;
- @JS('_renamedFinalField')
- external final int renamedFinalField;
-}
-
-class FieldsDart {
- int field = 1;
- int finalField = 1;
- int renamedField = 1;
- final int renamedFinalField = 1;
-}
-
-@JS()
-@staticInterop
-class GetSet {}
-
-extension on GetSet {
- external int get getSet;
- external set getSet(int val);
- @JS('_renamedGetSet')
- external int get renamedGetSet;
- @JS('_renamedGetSet')
- external set renamedGetSet(int val);
- @JS('_sameNameDifferentRenameGet')
- external int get sameNameDifferentRename;
- @JS('_sameNameDifferentRenameSet')
- external set sameNameDifferentRename(int val);
- @JS('_differentNameSameRename')
- external int get differentNameSameRenameGet;
- @JS('_differentNameSameRename')
- external set differentNameSameRenameSet(int val);
-}
-
-class GetSetDart {
- int getSet = 1;
- int renamedGetSet = 1;
- int sameNameDifferentRename = 1;
- int differentNameSameRenameGet = 1;
- int differentNameSameRenameSet = 1;
-}
+import 'functional_test_lib.dart';
void main() {
- var jsMethods = createStaticInteropMock<Methods, MethodsDart>(MethodsDart());
- expect(jsMethods.add(1, 1), 2);
- expect(jsMethods.nonExternal(), 0);
- expect(jsMethods.rename(), 1);
- expect(jsMethods.optionalAdd(1, 1), 2);
- expect(jsMethods.optionalAdd(1, 1, 1), 3);
- expect(jsMethods.optionalAdd(1, 1, 1, 1), 4);
- var dartFields = FieldsDart();
- var jsFields = createStaticInteropMock<Fields, FieldsDart>(dartFields);
- expect(jsFields.field, 1);
- expect(jsFields.finalField, 1);
- expect(jsFields.renamedField, 1);
- expect(jsFields.renamedFinalField, 1);
- // Modify the JS mock and check for updates in the Dart mock.
- jsFields.field = 2;
- jsFields.renamedField = 2;
- expect(dartFields.field, 2);
- expect(dartFields.renamedField, 2);
- // Modify the Dart mock and check for updates in the JS mock.
- dartFields.field = 3;
- dartFields.finalField = 3;
- dartFields.renamedField = 3;
- expect(jsFields.field, 3);
- expect(jsFields.finalField, 3);
- expect(jsFields.renamedField, 3);
- var dartGetSet = GetSetDart();
- var jsGetSet = createStaticInteropMock<GetSet, GetSetDart>(dartGetSet);
- expect(jsGetSet.getSet, 1);
- expect(jsGetSet.renamedGetSet, 1);
- expect(jsGetSet.sameNameDifferentRename, 1);
- expect(jsGetSet.differentNameSameRenameGet, 1);
- // Modify the JS mock and check for updates in the Dart mock.
- jsGetSet.getSet = 2;
- jsGetSet.renamedGetSet = 2;
- jsGetSet.sameNameDifferentRename = 2;
- jsGetSet.differentNameSameRenameSet = 2;
- expect(dartGetSet.getSet, 2);
- expect(dartGetSet.renamedGetSet, 2);
- expect(dartGetSet.sameNameDifferentRename, 2);
- expect(dartGetSet.differentNameSameRenameGet, 1);
- expect(dartGetSet.differentNameSameRenameSet, 2);
- // Modify the Dart mock and check for updates in the JS mock.
- dartGetSet.getSet = 3;
- dartGetSet.renamedGetSet = 3;
- dartGetSet.sameNameDifferentRename = 3;
- // Use different values to disambiguate.
- dartGetSet.differentNameSameRenameGet = 3;
- dartGetSet.differentNameSameRenameSet = 4;
- expect(jsGetSet.getSet, 3);
- expect(jsGetSet.renamedGetSet, 3);
- expect(jsGetSet.sameNameDifferentRename, 3);
- expect(jsGetSet.differentNameSameRenameGet, 3);
+ test();
}
diff --git a/tests/lib/js/static_interop_test/mock/functional_test_lib.dart b/tests/lib/js/static_interop_test/mock/functional_test_lib.dart
new file mode 100644
index 0000000..69d5ec9
--- /dev/null
+++ b/tests/lib/js/static_interop_test/mock/functional_test_lib.dart
@@ -0,0 +1,137 @@
+// 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.
+
+// Test basic functionality of `createStaticInteropMock`. Basic methods, fields
+// (final and not), getters, and setters are tested along with potential
+// renames.
+
+import 'package:expect/minitest.dart';
+import 'package:js/js.dart';
+import 'package:js/js_util.dart';
+
+@JS()
+@staticInterop
+class Methods {}
+
+extension on Methods {
+ external int add(int a, int b);
+ // Sanity-check that non-externals are unaffected.
+ int nonExternal() => 0;
+ @JS('_rename')
+ external int rename();
+ external int optionalAdd(int a, int b, [int c = 0, int? d]);
+}
+
+class MethodsDart {
+ int add(int a, int b) => a + b;
+ int nonExternal() => 1;
+ int rename() => 1;
+ int optionalAdd(int a, int b, [int? c, int? d]) =>
+ a + b + (c ?? 0) + (d ?? 0);
+}
+
+@JS()
+@staticInterop
+class Fields {}
+
+extension on Fields {
+ external int field;
+ external final int finalField;
+ @JS('_renamedField')
+ external int renamedField;
+ @JS('_renamedFinalField')
+ external final int renamedFinalField;
+}
+
+class FieldsDart {
+ int field = 1;
+ int finalField = 1;
+ int renamedField = 1;
+ final int renamedFinalField = 1;
+}
+
+@JS()
+@staticInterop
+class GetSet {}
+
+extension on GetSet {
+ external int get getSet;
+ external set getSet(int val);
+ @JS('_renamedGetSet')
+ external int get renamedGetSet;
+ @JS('_renamedGetSet')
+ external set renamedGetSet(int val);
+ @JS('_sameNameDifferentRenameGet')
+ external int get sameNameDifferentRename;
+ @JS('_sameNameDifferentRenameSet')
+ external set sameNameDifferentRename(int val);
+ @JS('_differentNameSameRename')
+ external int get differentNameSameRenameGet;
+ @JS('_differentNameSameRename')
+ external set differentNameSameRenameSet(int val);
+}
+
+class GetSetDart {
+ int getSet = 1;
+ int renamedGetSet = 1;
+ int sameNameDifferentRename = 1;
+ int differentNameSameRenameGet = 1;
+ int differentNameSameRenameSet = 1;
+}
+
+void test([Object? proto]) {
+ var jsMethods =
+ createStaticInteropMock<Methods, MethodsDart>(MethodsDart(), proto);
+ expect(jsMethods.add(1, 1), 2);
+ expect(jsMethods.nonExternal(), 0);
+ expect(jsMethods.rename(), 1);
+ expect(jsMethods.optionalAdd(1, 1), 2);
+ expect(jsMethods.optionalAdd(1, 1, 1), 3);
+ expect(jsMethods.optionalAdd(1, 1, 1, 1), 4);
+ var dartFields = FieldsDart();
+ var jsFields = createStaticInteropMock<Fields, FieldsDart>(dartFields, proto);
+ expect(jsFields.field, 1);
+ expect(jsFields.finalField, 1);
+ expect(jsFields.renamedField, 1);
+ expect(jsFields.renamedFinalField, 1);
+ // Modify the JS mock and check for updates in the Dart mock.
+ jsFields.field = 2;
+ jsFields.renamedField = 2;
+ expect(dartFields.field, 2);
+ expect(dartFields.renamedField, 2);
+ // Modify the Dart mock and check for updates in the JS mock.
+ dartFields.field = 3;
+ dartFields.finalField = 3;
+ dartFields.renamedField = 3;
+ expect(jsFields.field, 3);
+ expect(jsFields.finalField, 3);
+ expect(jsFields.renamedField, 3);
+ var dartGetSet = GetSetDart();
+ var jsGetSet = createStaticInteropMock<GetSet, GetSetDart>(dartGetSet, proto);
+ expect(jsGetSet.getSet, 1);
+ expect(jsGetSet.renamedGetSet, 1);
+ expect(jsGetSet.sameNameDifferentRename, 1);
+ expect(jsGetSet.differentNameSameRenameGet, 1);
+ // Modify the JS mock and check for updates in the Dart mock.
+ jsGetSet.getSet = 2;
+ jsGetSet.renamedGetSet = 2;
+ jsGetSet.sameNameDifferentRename = 2;
+ jsGetSet.differentNameSameRenameSet = 2;
+ expect(dartGetSet.getSet, 2);
+ expect(dartGetSet.renamedGetSet, 2);
+ expect(dartGetSet.sameNameDifferentRename, 2);
+ expect(dartGetSet.differentNameSameRenameGet, 1);
+ expect(dartGetSet.differentNameSameRenameSet, 2);
+ // Modify the Dart mock and check for updates in the JS mock.
+ dartGetSet.getSet = 3;
+ dartGetSet.renamedGetSet = 3;
+ dartGetSet.sameNameDifferentRename = 3;
+ // Use different values to disambiguate.
+ dartGetSet.differentNameSameRenameGet = 3;
+ dartGetSet.differentNameSameRenameSet = 4;
+ expect(jsGetSet.getSet, 3);
+ expect(jsGetSet.renamedGetSet, 3);
+ expect(jsGetSet.sameNameDifferentRename, 3);
+ expect(jsGetSet.differentNameSameRenameGet, 3);
+}
diff --git a/tests/lib/js/static_interop_test/mock/proto_test.dart b/tests/lib/js/static_interop_test/mock/proto_test.dart
new file mode 100644
index 0000000..647cd58
--- /dev/null
+++ b/tests/lib/js/static_interop_test/mock/proto_test.dart
@@ -0,0 +1,39 @@
+// 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.
+
+// Test that providing a proto object to createStaticInteropMock does not break
+// any functionality, and allows instanceof/is checks to pass.
+
+@JS()
+library proto_test;
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+import 'package:js/js.dart';
+import 'package:js/js_util.dart';
+
+import 'functional_test_lib.dart' as functional_test;
+
+@JS('Window.prototype')
+external Object get windowProto;
+
+@JS('Window')
+external Object get windowType;
+
+@JS()
+@staticInterop
+class JSWindow {}
+
+class DartWindow {}
+
+void main() {
+ // Test that everything still works the same.
+ functional_test.test(windowProto);
+ // Test instanceof/is checks.
+ var jsMock =
+ createStaticInteropMock<JSWindow, DartWindow>(DartWindow(), windowProto);
+ expect(jsMock is Window, true);
+ expect(instanceof(jsMock, windowType), true);
+}
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index c68cbad..921086b 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -15,6 +15,7 @@
js/js_util/javascriptobject_extensions_test: SkipByDesign # Uses dart:html.
js/static_interop_test/constants_test: SkipByDesign # Uses dart:html.
js/static_interop_test/futurevaluetype_test: SkipByDesign # Uses dart:html.
+js/static_interop_test/mock/proto_test: SkipByDesign # Uses dart:html.
js/static_interop_test/supertype_transform_test: SkipByDesign # Uses dart:html.
[ $runtime == dart_precompiled ]
diff --git a/tests/lib_2/js/static_interop_test/mock/functional_test.dart b/tests/lib_2/js/static_interop_test/mock/functional_test.dart
index f44f0cb..a43df9a 100644
--- a/tests/lib_2/js/static_interop_test/mock/functional_test.dart
+++ b/tests/lib_2/js/static_interop_test/mock/functional_test.dart
@@ -2,135 +2,8 @@
// 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.
-// Test basic functionality of `createStaticInteropMock`. Basic methods, fields
-// (final and not), getters, and setters are tested along with potential
-// renames.
-
-import 'package:expect/minitest.dart';
-import 'package:js/js.dart';
-import 'package:js/js_util.dart';
-
-@JS()
-@staticInterop
-class Methods {}
-
-extension on Methods {
- external int add(int a, int b);
- // Sanity-check that non-externals are unaffected.
- int nonExternal() => 0;
- @JS('_rename')
- external int rename();
- external int optionalAdd(int a, int b, [int c = 0, int? d]);
-}
-
-class MethodsDart {
- int add(int a, int b) => a + b;
- int nonExternal() => 1;
- int rename() => 1;
- int optionalAdd(int a, int b, [int? c, int? d]) =>
- a + b + (c ?? 0) + (d ?? 0);
-}
-
-@JS()
-@staticInterop
-class Fields {}
-
-extension on Fields {
- external int field;
- external final int finalField;
- @JS('_renamedField')
- external int renamedField;
- @JS('_renamedFinalField')
- external final int renamedFinalField;
-}
-
-class FieldsDart {
- int field = 1;
- int finalField = 1;
- int renamedField = 1;
- final int renamedFinalField = 1;
-}
-
-@JS()
-@staticInterop
-class GetSet {}
-
-extension on GetSet {
- external int get getSet;
- external set getSet(int val);
- @JS('_renamedGetSet')
- external int get renamedGetSet;
- @JS('_renamedGetSet')
- external set renamedGetSet(int val);
- @JS('_sameNameDifferentRenameGet')
- external int get sameNameDifferentRename;
- @JS('_sameNameDifferentRenameSet')
- external set sameNameDifferentRename(int val);
- @JS('_differentNameSameRename')
- external int get differentNameSameRenameGet;
- @JS('_differentNameSameRename')
- external set differentNameSameRenameSet(int val);
-}
-
-class GetSetDart {
- int getSet = 1;
- int renamedGetSet = 1;
- int sameNameDifferentRename = 1;
- int differentNameSameRenameGet = 1;
- int differentNameSameRenameSet = 1;
-}
+import 'functional_test_lib.dart';
void main() {
- var jsMethods = createStaticInteropMock<Methods, MethodsDart>(MethodsDart());
- expect(jsMethods.add(1, 1), 2);
- expect(jsMethods.nonExternal(), 0);
- expect(jsMethods.rename(), 1);
- expect(jsMethods.optionalAdd(1, 1), 2);
- expect(jsMethods.optionalAdd(1, 1, 1), 3);
- expect(jsMethods.optionalAdd(1, 1, 1, 1), 4);
- var dartFields = FieldsDart();
- var jsFields = createStaticInteropMock<Fields, FieldsDart>(dartFields);
- expect(jsFields.field, 1);
- expect(jsFields.finalField, 1);
- expect(jsFields.renamedField, 1);
- expect(jsFields.renamedFinalField, 1);
- // Modify the JS mock and check for updates in the Dart mock.
- jsFields.field = 2;
- jsFields.renamedField = 2;
- expect(dartFields.field, 2);
- expect(dartFields.renamedField, 2);
- // Modify the Dart mock and check for updates in the JS mock.
- dartFields.field = 3;
- dartFields.finalField = 3;
- dartFields.renamedField = 3;
- expect(jsFields.field, 3);
- expect(jsFields.finalField, 3);
- expect(jsFields.renamedField, 3);
- var dartGetSet = GetSetDart();
- var jsGetSet = createStaticInteropMock<GetSet, GetSetDart>(dartGetSet);
- expect(jsGetSet.getSet, 1);
- expect(jsGetSet.renamedGetSet, 1);
- expect(jsGetSet.sameNameDifferentRename, 1);
- expect(jsGetSet.differentNameSameRenameGet, 1);
- // Modify the JS mock and check for updates in the Dart mock.
- jsGetSet.getSet = 2;
- jsGetSet.renamedGetSet = 2;
- jsGetSet.sameNameDifferentRename = 2;
- jsGetSet.differentNameSameRenameSet = 2;
- expect(dartGetSet.getSet, 2);
- expect(dartGetSet.renamedGetSet, 2);
- expect(dartGetSet.sameNameDifferentRename, 2);
- expect(dartGetSet.differentNameSameRenameGet, 1);
- expect(dartGetSet.differentNameSameRenameSet, 2);
- // Modify the Dart mock and check for updates in the JS mock.
- dartGetSet.getSet = 3;
- dartGetSet.renamedGetSet = 3;
- dartGetSet.sameNameDifferentRename = 3;
- // Use different values to disambiguate.
- dartGetSet.differentNameSameRenameGet = 3;
- dartGetSet.differentNameSameRenameSet = 4;
- expect(jsGetSet.getSet, 3);
- expect(jsGetSet.renamedGetSet, 3);
- expect(jsGetSet.sameNameDifferentRename, 3);
- expect(jsGetSet.differentNameSameRenameGet, 3);
+ test();
}
diff --git a/tests/lib_2/js/static_interop_test/mock/functional_test_lib.dart b/tests/lib_2/js/static_interop_test/mock/functional_test_lib.dart
new file mode 100644
index 0000000..69d5ec9
--- /dev/null
+++ b/tests/lib_2/js/static_interop_test/mock/functional_test_lib.dart
@@ -0,0 +1,137 @@
+// 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.
+
+// Test basic functionality of `createStaticInteropMock`. Basic methods, fields
+// (final and not), getters, and setters are tested along with potential
+// renames.
+
+import 'package:expect/minitest.dart';
+import 'package:js/js.dart';
+import 'package:js/js_util.dart';
+
+@JS()
+@staticInterop
+class Methods {}
+
+extension on Methods {
+ external int add(int a, int b);
+ // Sanity-check that non-externals are unaffected.
+ int nonExternal() => 0;
+ @JS('_rename')
+ external int rename();
+ external int optionalAdd(int a, int b, [int c = 0, int? d]);
+}
+
+class MethodsDart {
+ int add(int a, int b) => a + b;
+ int nonExternal() => 1;
+ int rename() => 1;
+ int optionalAdd(int a, int b, [int? c, int? d]) =>
+ a + b + (c ?? 0) + (d ?? 0);
+}
+
+@JS()
+@staticInterop
+class Fields {}
+
+extension on Fields {
+ external int field;
+ external final int finalField;
+ @JS('_renamedField')
+ external int renamedField;
+ @JS('_renamedFinalField')
+ external final int renamedFinalField;
+}
+
+class FieldsDart {
+ int field = 1;
+ int finalField = 1;
+ int renamedField = 1;
+ final int renamedFinalField = 1;
+}
+
+@JS()
+@staticInterop
+class GetSet {}
+
+extension on GetSet {
+ external int get getSet;
+ external set getSet(int val);
+ @JS('_renamedGetSet')
+ external int get renamedGetSet;
+ @JS('_renamedGetSet')
+ external set renamedGetSet(int val);
+ @JS('_sameNameDifferentRenameGet')
+ external int get sameNameDifferentRename;
+ @JS('_sameNameDifferentRenameSet')
+ external set sameNameDifferentRename(int val);
+ @JS('_differentNameSameRename')
+ external int get differentNameSameRenameGet;
+ @JS('_differentNameSameRename')
+ external set differentNameSameRenameSet(int val);
+}
+
+class GetSetDart {
+ int getSet = 1;
+ int renamedGetSet = 1;
+ int sameNameDifferentRename = 1;
+ int differentNameSameRenameGet = 1;
+ int differentNameSameRenameSet = 1;
+}
+
+void test([Object? proto]) {
+ var jsMethods =
+ createStaticInteropMock<Methods, MethodsDart>(MethodsDart(), proto);
+ expect(jsMethods.add(1, 1), 2);
+ expect(jsMethods.nonExternal(), 0);
+ expect(jsMethods.rename(), 1);
+ expect(jsMethods.optionalAdd(1, 1), 2);
+ expect(jsMethods.optionalAdd(1, 1, 1), 3);
+ expect(jsMethods.optionalAdd(1, 1, 1, 1), 4);
+ var dartFields = FieldsDart();
+ var jsFields = createStaticInteropMock<Fields, FieldsDart>(dartFields, proto);
+ expect(jsFields.field, 1);
+ expect(jsFields.finalField, 1);
+ expect(jsFields.renamedField, 1);
+ expect(jsFields.renamedFinalField, 1);
+ // Modify the JS mock and check for updates in the Dart mock.
+ jsFields.field = 2;
+ jsFields.renamedField = 2;
+ expect(dartFields.field, 2);
+ expect(dartFields.renamedField, 2);
+ // Modify the Dart mock and check for updates in the JS mock.
+ dartFields.field = 3;
+ dartFields.finalField = 3;
+ dartFields.renamedField = 3;
+ expect(jsFields.field, 3);
+ expect(jsFields.finalField, 3);
+ expect(jsFields.renamedField, 3);
+ var dartGetSet = GetSetDart();
+ var jsGetSet = createStaticInteropMock<GetSet, GetSetDart>(dartGetSet, proto);
+ expect(jsGetSet.getSet, 1);
+ expect(jsGetSet.renamedGetSet, 1);
+ expect(jsGetSet.sameNameDifferentRename, 1);
+ expect(jsGetSet.differentNameSameRenameGet, 1);
+ // Modify the JS mock and check for updates in the Dart mock.
+ jsGetSet.getSet = 2;
+ jsGetSet.renamedGetSet = 2;
+ jsGetSet.sameNameDifferentRename = 2;
+ jsGetSet.differentNameSameRenameSet = 2;
+ expect(dartGetSet.getSet, 2);
+ expect(dartGetSet.renamedGetSet, 2);
+ expect(dartGetSet.sameNameDifferentRename, 2);
+ expect(dartGetSet.differentNameSameRenameGet, 1);
+ expect(dartGetSet.differentNameSameRenameSet, 2);
+ // Modify the Dart mock and check for updates in the JS mock.
+ dartGetSet.getSet = 3;
+ dartGetSet.renamedGetSet = 3;
+ dartGetSet.sameNameDifferentRename = 3;
+ // Use different values to disambiguate.
+ dartGetSet.differentNameSameRenameGet = 3;
+ dartGetSet.differentNameSameRenameSet = 4;
+ expect(jsGetSet.getSet, 3);
+ expect(jsGetSet.renamedGetSet, 3);
+ expect(jsGetSet.sameNameDifferentRename, 3);
+ expect(jsGetSet.differentNameSameRenameGet, 3);
+}
diff --git a/tests/lib_2/js/static_interop_test/mock/proto_test.dart b/tests/lib_2/js/static_interop_test/mock/proto_test.dart
new file mode 100644
index 0000000..647cd58
--- /dev/null
+++ b/tests/lib_2/js/static_interop_test/mock/proto_test.dart
@@ -0,0 +1,39 @@
+// 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.
+
+// Test that providing a proto object to createStaticInteropMock does not break
+// any functionality, and allows instanceof/is checks to pass.
+
+@JS()
+library proto_test;
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+import 'package:js/js.dart';
+import 'package:js/js_util.dart';
+
+import 'functional_test_lib.dart' as functional_test;
+
+@JS('Window.prototype')
+external Object get windowProto;
+
+@JS('Window')
+external Object get windowType;
+
+@JS()
+@staticInterop
+class JSWindow {}
+
+class DartWindow {}
+
+void main() {
+ // Test that everything still works the same.
+ functional_test.test(windowProto);
+ // Test instanceof/is checks.
+ var jsMock =
+ createStaticInteropMock<JSWindow, DartWindow>(DartWindow(), windowProto);
+ expect(jsMock is Window, true);
+ expect(instanceof(jsMock, windowType), true);
+}
diff --git a/tests/lib_2/lib_2.status b/tests/lib_2/lib_2.status
index 1688cf9..15d4e48 100644
--- a/tests/lib_2/lib_2.status
+++ b/tests/lib_2/lib_2.status
@@ -15,6 +15,7 @@
js/js_util/javascriptobject_extensions_test: SkipByDesign # Uses dart:html.
js/static_interop_test/constants_test: SkipByDesign # Uses dart:html.
js/static_interop_test/futurevaluetype_test: SkipByDesign # Uses dart:html.
+js/static_interop_test/mock/proto_test: SkipByDesign # Uses dart:html.
js/static_interop_test/supertype_transform_test: SkipByDesign # Uses dart:html.
[ $runtime == dart_precompiled ]