[pkg:js] Disallow all operators in JS classes

Closes https://github.com/dart-lang/sdk/issues/48515

Expands existing checks for index operations to all operators. This
only affects instance members and not extension members.

Change-Id: I8cbb5b12a49539ea502e4396e1b469ffb0e17d5e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/235980
Reviewed-by: Riley Porter <rileyporter@google.com>
Reviewed-by: Sigmund Cherem <sigmund@google.com>
Commit-Queue: Srujan Gaddam <srujzs@google.com>
This commit is contained in:
Srujan Gaddam 2022-03-09 01:48:24 +00:00 committed by Commit Bot
parent 75e03d7875
commit f8933dda8d
6 changed files with 367 additions and 29 deletions

View file

@ -6568,17 +6568,6 @@ const MessageCode messageJsInteropExternalMemberNotJSAnnotated = const MessageCo
correctionMessage:
r"""Try removing the 'external' keyword or adding a JS interop annotation.""");
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeJsInteropIndexNotSupported =
messageJsInteropIndexNotSupported;
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const MessageCode messageJsInteropIndexNotSupported = const MessageCode(
"JsInteropIndexNotSupported",
problemMessage:
r"""JS interop classes do not support [] and []= operator methods.""",
correctionMessage: r"""Try replacing with a normal method.""");
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<
Message Function(
@ -6684,6 +6673,16 @@ const MessageCode messageJsInteropNonExternalMember = const MessageCode(
r"""This JS interop member must be annotated with `external`. Only factories and static methods can be non-external.""",
correctionMessage: r"""Try annotating the member with `external`.""");
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeJsInteropOperatorsNotSupported =
messageJsInteropOperatorsNotSupported;
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const MessageCode messageJsInteropOperatorsNotSupported = const MessageCode(
"JsInteropOperatorsNotSupported",
problemMessage: r"""JS interop classes do not support operator methods.""",
correctionMessage: r"""Try replacing this with a normal method.""");
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<Message Function(String name)>
templateJsInteropStaticInteropWithInstanceMembers =

View file

@ -14,10 +14,10 @@ import 'package:_fe_analyzer_shared/src/messages/codes.dart'
messageJsInteropEnclosingClassJSAnnotationContext,
messageJsInteropExternalExtensionMemberOnTypeInvalid,
messageJsInteropExternalMemberNotJSAnnotated,
messageJsInteropIndexNotSupported,
messageJsInteropNamedParameters,
messageJsInteropNonExternalConstructor,
messageJsInteropNonExternalMember,
messageJsInteropOperatorsNotSupported,
templateJsInteropDartClassExtendsJSClass,
templateJsInteropStaticInteropWithInstanceMembers,
templateJsInteropStaticInteropWithNonStaticSupertype,
@ -220,10 +220,9 @@ class JsInteropChecks extends RecursiveVisitor {
_checkDisallowedExternal(procedure);
} else {
// Check JS interop indexing.
if (!procedure.isStatic &&
(procedure.name.text == '[]=' || procedure.name.text == '[]')) {
if (!procedure.isStatic && procedure.kind == ProcedureKind.Operator) {
_diagnosticsReporter.report(
messageJsInteropIndexNotSupported,
messageJsInteropOperatorsNotSupported,
procedure.fileOffset,
procedure.name.text.length,
procedure.fileUri);

View file

@ -546,8 +546,6 @@ JsInteropExternalExtensionMemberOnTypeInvalid/analyzerCode: Fail # Web compiler
JsInteropExternalExtensionMemberOnTypeInvalid/example: Fail # Web compiler specific
JsInteropExternalMemberNotJSAnnotated/analyzerCode: Fail # Web compiler specific
JsInteropExternalMemberNotJSAnnotated/example: Fail # Web compiler specific
JsInteropIndexNotSupported/analyzerCode: Fail # Web compiler specific
JsInteropIndexNotSupported/example: Fail # Web compiler specific
JsInteropJSClassExtendsDartClass/analyzerCode: Fail # Web compiler specific
JsInteropJSClassExtendsDartClass/example: Fail # Web compiler specific
JsInteropNamedParameters/analyzerCode: Fail # Web compiler specific
@ -558,6 +556,8 @@ JsInteropNonExternalConstructor/analyzerCode: Fail # Web compiler specific
JsInteropNonExternalConstructor/example: Fail # Web compiler specific
JsInteropNonExternalMember/analyzerCode: Fail # Web compiler specific
JsInteropNonExternalMember/example: Fail # Web compiler specific
JsInteropOperatorsNotSupported/analyzerCode: Fail # Web compiler specific
JsInteropOperatorsNotSupported/example: Fail # Web compiler specific
JsInteropStaticInteropWithInstanceMembers/analyzerCode: Fail # Web compiler specific
JsInteropStaticInteropWithInstanceMembers/example: Fail # Web compiler specific
JsInteropStaticInteropWithNonStaticSupertype/analyzerCode: Fail # Web compiler specific

View file

@ -5096,18 +5096,6 @@ JsInteropExternalMemberNotJSAnnotated:
problemMessage: "Only JS interop members may be 'external'."
correctionMessage: "Try removing the 'external' keyword or adding a JS interop annotation."
JsInteropIndexNotSupported:
problemMessage: "JS interop classes do not support [] and []= operator methods."
correctionMessage: "Try replacing with a normal method."
JsInteropStaticInteropWithInstanceMembers:
problemMessage: "JS interop class '#name' with `@staticInterop` annotation cannot declare instance members."
correctionMessage: "Try moving the instance member to a static extension."
JsInteropStaticInteropWithNonStaticSupertype:
problemMessage: "JS interop class '#name' has an `@staticInterop` annotation, but has supertype '#name2', which is non-static."
correctionMessage: "Try marking the supertype as a static interop class using `@staticInterop`."
JsInteropJSClassExtendsDartClass:
problemMessage: "JS interop class '#name' cannot extend Dart class '#name2'."
correctionMessage: "Try removing the JS interop annotation or adding it to the parent class."
@ -5128,6 +5116,18 @@ JsInteropNonExternalMember:
problemMessage: "This JS interop member must be annotated with `external`. Only factories and static methods can be non-external."
correctionMessage: "Try annotating the member with `external`."
JsInteropOperatorsNotSupported:
problemMessage: "JS interop classes do not support operator methods."
correctionMessage: "Try replacing this with a normal method."
JsInteropStaticInteropWithInstanceMembers:
problemMessage: "JS interop class '#name' with `@staticInterop` annotation cannot declare instance members."
correctionMessage: "Try moving the instance member to a static extension."
JsInteropStaticInteropWithNonStaticSupertype:
problemMessage: "JS interop class '#name' has an `@staticInterop` annotation, but has supertype '#name2', which is non-static."
correctionMessage: "Try marking the supertype as a static interop class using `@staticInterop`."
DefaultListConstructorError:
problemMessage: "Can't use the default List constructor."
correctionMessage: "Try using List.filled instead."

View file

@ -0,0 +1,170 @@
// 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.
@JS()
library operator_test;
import 'package:js/js.dart';
@JS()
class JSClass {
// https://dart.dev/guides/language/language-tour#_operators for the list of
// operators allowed by the language.
external void operator <(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator >(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator <=(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator >=(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator -(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator +(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator /(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator ~/(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator *(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator %(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator |(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator ^(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator &(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator <<(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator >>(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator >>>(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator [](_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator []=(_, __);
// ^
// [web] JS interop classes do not support operator methods.
external void operator ~();
// ^
// [web] JS interop classes do not support operator methods.
external bool operator ==(_);
// ^
// [web] JS interop classes do not support operator methods.
}
@JS()
@anonymous
class AnonymousClass {
external void operator <(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator >(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator <=(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator >=(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator -(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator +(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator /(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator ~/(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator *(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator %(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator |(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator ^(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator &(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator <<(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator >>(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator >>>(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator [](_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator []=(_, __);
// ^
// [web] JS interop classes do not support operator methods.
external void operator ~();
// ^
// [web] JS interop classes do not support operator methods.
external bool operator ==(_);
// ^
// [web] JS interop classes do not support operator methods.
}
@JS()
class JSClassExtensions {}
extension _ on JSClassExtensions {
// External operators in extensions are allowed for now, but don't work as
// intended. Specific operators will need to be allowlisted in the future.
// TODO(srujzs): Remove this test once we do that.
external void operator <(_);
external void operator >(_);
external void operator <=(_);
external void operator >=(_);
external void operator -(_);
external void operator +(_);
external void operator /(_);
external void operator ~/(_);
external void operator *(_);
external void operator %(_);
external void operator |(_);
external void operator ^(_);
external void operator &(_);
external void operator <<(_);
external void operator >>(_);
external void operator >>>(_);
external void operator [](_);
external void operator []=(_, __);
external void operator ~();
// No `==` as it's an `Object` method.
}
void main() {}

View file

@ -0,0 +1,170 @@
// 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.
@JS()
library operator_test;
import 'package:js/js.dart';
@JS()
class JSClass {
// https://dart.dev/guides/language/language-tour#_operators for the list of
// operators allowed by the language.
external void operator <(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator >(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator <=(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator >=(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator -(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator +(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator /(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator ~/(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator *(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator %(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator |(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator ^(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator &(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator <<(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator >>(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator >>>(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator [](_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator []=(_, __);
// ^
// [web] JS interop classes do not support operator methods.
external void operator ~();
// ^
// [web] JS interop classes do not support operator methods.
external bool operator ==(_);
// ^
// [web] JS interop classes do not support operator methods.
}
@JS()
@anonymous
class AnonymousClass {
external void operator <(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator >(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator <=(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator >=(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator -(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator +(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator /(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator ~/(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator *(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator %(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator |(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator ^(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator &(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator <<(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator >>(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator >>>(_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator [](_);
// ^
// [web] JS interop classes do not support operator methods.
external void operator []=(_, __);
// ^
// [web] JS interop classes do not support operator methods.
external void operator ~();
// ^
// [web] JS interop classes do not support operator methods.
external bool operator ==(_);
// ^
// [web] JS interop classes do not support operator methods.
}
@JS()
class JSClassExtensions {}
extension _ on JSClassExtensions {
// External operators in extensions are allowed for now, but don't work as
// intended. Specific operators will need to be allowlisted in the future.
// TODO(srujzs): Remove this test once we do that.
external void operator <(_);
external void operator >(_);
external void operator <=(_);
external void operator >=(_);
external void operator -(_);
external void operator +(_);
external void operator /(_);
external void operator ~/(_);
external void operator *(_);
external void operator %(_);
external void operator |(_);
external void operator ^(_);
external void operator &(_);
external void operator <<(_);
external void operator >>(_);
external void operator >>>(_);
external void operator [](_);
external void operator []=(_, __);
external void operator ~();
// No `==` as it's an `Object` method.
}
void main() {}