[dart:js_interop] Move JS types to extension types

- Removes @staticInterop JS types declarations in favor of
typedefs (the function types' reified types and the typed data's
reified types have changed to make the type hierarchy work in the
JS backends).
- Adds extension types to dart:js_interop
- Adds a fromInteropObject helper to JSObject to avoid casting to
an extension type
- Deletes now stale tests
- Refactors some dart2wasm @staticInterop declarations since they
can no longer implement JS types
- Updates extension types tests to use the prefix extension_type
instead of inline_class
- Updates comments

CoreLibraryReviewExempt: Backend-specific library.
Change-Id: Ibe04afac9585ddb99fcf6dbaa7f12050d8b876dc
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/332860
Reviewed-by: Sigmund Cherem <sigmund@google.com>
Commit-Queue: Srujan Gaddam <srujzs@google.com>
This commit is contained in:
Srujan Gaddam 2023-12-06 21:59:58 +00:00 committed by Commit Queue
parent 5d4e742a67
commit b1a7ca77e0
31 changed files with 264 additions and 872 deletions

View file

@ -16,6 +16,20 @@
[#51896]: https://github.com/dart-lang/sdk/issues/51896
#### `dart:js_interop`
- **Breaking Change in the representation of JS types** [#52687][]: JS types
like `JSAny` were previously represented using a custom erasure of
`@staticInterop` types that were compiler-specific. They are now represented
as extension types where their representation types are compiler-specific.
This means that user-defined `@staticInterop` types that implemented `JSAny`
or `JSObject` can no longer do so and need to use
`JSObject.fromInteropObject`. Going forward, it's recommended to use extension
types to define interop APIs. Those extension types can still implement JS
types.
[#52687]: https://github.com/dart-lang/sdk/issues/52687
#### `dart:typed_data`
- **BREAKING CHANGE** (https://github.com/dart-lang/sdk/issues/53218) The

View file

@ -9123,39 +9123,6 @@ Message _withArgumentsJsInteropStaticInteropWithInstanceMembers(String name) {
arguments: {'name': name});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<Message Function(String name, String name2)>
templateJsInteropStaticInteropWithInvalidJsTypesSupertype =
const Template<Message Function(String name, String name2)>(
"JsInteropStaticInteropWithInvalidJsTypesSupertype",
problemMessageTemplate:
r"""`@staticInterop` class '#name' cannot have '#name2' as a supertype. `JSObject` and `JSAny` are the only valid supertypes from `dart:js_interop` for `@staticInterop` classes.""",
correctionMessageTemplate:
r"""Try subtyping `JSObject` or `JSAny` instead, or try casting an object of type '#name' to '#name2' when needed.""",
withArguments:
_withArgumentsJsInteropStaticInteropWithInvalidJsTypesSupertype);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Message Function(String name, String name2)>
codeJsInteropStaticInteropWithInvalidJsTypesSupertype =
const Code<Message Function(String name, String name2)>(
"JsInteropStaticInteropWithInvalidJsTypesSupertype",
);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
Message _withArgumentsJsInteropStaticInteropWithInvalidJsTypesSupertype(
String name, String name2) {
if (name.isEmpty) throw 'No name provided';
name = demangleMixinApplicationName(name);
if (name2.isEmpty) throw 'No name provided';
name2 = demangleMixinApplicationName(name2);
return new Message(codeJsInteropStaticInteropWithInvalidJsTypesSupertype,
problemMessage:
"""`@staticInterop` class '${name}' cannot have '${name2}' as a supertype. `JSObject` and `JSAny` are the only valid supertypes from `dart:js_interop` for `@staticInterop` classes.""",
correctionMessage: """Try subtyping `JSObject` or `JSAny` instead, or try casting an object of type '${name}' to '${name2}' when needed.""",
arguments: {'name': name, 'name2': name2});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<Message Function(String name, String name2)>
templateJsInteropStaticInteropWithNonStaticSupertype =

View file

@ -31,7 +31,6 @@ import 'package:_fe_analyzer_shared/src/messages/codes.dart'
templateJsInteropNonStaticWithStaticInteropSupertype,
templateJsInteropStaticInteropNoJSAnnotation,
templateJsInteropStaticInteropWithInstanceMembers,
templateJsInteropStaticInteropWithInvalidJsTypesSupertype,
templateJsInteropStaticInteropWithNonStaticSupertype,
templateJsInteropObjectLiteralConstructorPositionalParameters,
templateJsInteropNativeClassInAnnotation,
@ -227,13 +226,17 @@ class JsInteropChecks extends RecursiveVisitor {
report(templateJsInteropStaticInteropNoJSAnnotation
.withArguments(node.name));
}
if (superclass != null) {
_checkSuperclassOfStaticInteropClass(node, superclass);
if (superclass != null && !hasStaticInteropAnnotation(superclass)) {
report(templateJsInteropStaticInteropWithNonStaticSupertype
.withArguments(node.name, superclass.name));
}
// Validate that superinterfaces are all valid supertypes as well. Note
// that mixins are already disallowed and therefore are not checked here.
for (final supertype in node.implementedTypes) {
_checkSuperclassOfStaticInteropClass(node, supertype.classNode);
if (!hasStaticInteropAnnotation(supertype.classNode)) {
report(templateJsInteropStaticInteropWithNonStaticSupertype
.withArguments(node.name, supertype.classNode.name));
}
}
} else {
// For classes, `dart:js_interop`'s `@JS` can only be used with
@ -819,39 +822,6 @@ class JsInteropChecks extends RecursiveVisitor {
}
}
/// Reports an error if @staticInterop classes extends or implements a
/// non-@staticInterop type or an invalid dart:_js_types type.
void _checkSuperclassOfStaticInteropClass(Class node, Class superclass) {
void report(Message message) => _reporter.report(
message, node.fileOffset, node.name.length, node.fileUri);
if (!hasStaticInteropAnnotation(superclass)) {
report(templateJsInteropStaticInteropWithNonStaticSupertype.withArguments(
node.name, superclass.name));
} else {
// dart:_js_types @staticInterop types are special. They are custom-erased
// to different types at runtime. User @staticInterop types are always
// erased to JavaScriptObject. As such, this means that we should only
// allow users to subtype dart:_js_types types that erase to a
// T >: JavaScriptObject. Currently, this is only JSObject and JSAny.
// TODO(srujzs): This error should be temporary. In the future, once we
// have extension types that can implement concrete classes, we can move
// all the dart:_js_types that aren't JSObject and JSAny to extension
// types. Then, this error becomes redundant. This would also allow us to
// idiomatically add type parameters to JSArray and JSPromise.
final superclassUri = superclass.enclosingLibrary.importUri;
// Make an exception for some internal libraries.
final allowList = {'_js_types', '_js_helper'};
if (superclassUri.isScheme('dart') &&
superclassUri.path == '_js_types' &&
!allowList.contains(node.enclosingLibrary.importUri.path) &&
superclass.name != 'JSAny' &&
superclass.name != 'JSObject') {
report(templateJsInteropStaticInteropWithInvalidJsTypesSupertype
.withArguments(node.name, superclass.name));
}
}
}
/// If [procedure] is a generated procedure that represents a relevant
/// tear-off, return the torn-off member.
///
@ -944,9 +914,6 @@ class JsInteropChecks extends RecursiveVisitor {
.isInteropExtensionType(type.extensionTypeDeclaration)) {
return true;
}
// Extension types where the representation type is allowed are okay.
// TODO(srujzs): Once the CFE pre-computes the concrete type, don't
// recurse.
return _isAllowedExternalType(type.extensionTypeErasure);
}
return false;

View file

@ -28,8 +28,8 @@ class ExportCreator extends Transformer {
final Procedure _functionToJS;
final Procedure _getProperty;
final Procedure _globalContext;
final Class _jsAny;
final Class _jsObject;
final ExtensionTypeDeclaration _jsAny;
final ExtensionTypeDeclaration _jsObject;
final Procedure _setProperty;
final Procedure _stringToJS;
final StaticInteropMockValidator _staticInteropMockValidator;
@ -51,9 +51,9 @@ class ExportCreator extends Transformer {
_globalContext = _typeEnvironment.coreTypes.index
.getTopLevelProcedure('dart:js_interop', 'get:globalContext'),
_jsAny = _typeEnvironment.coreTypes.index
.getClass('dart:_js_types', 'JSAny'),
.getExtensionType('dart:js_interop', 'JSAny'),
_jsObject = _typeEnvironment.coreTypes.index
.getClass('dart:_js_types', 'JSObject'),
.getExtensionType('dart:js_interop', 'JSObject'),
_setProperty = _typeEnvironment.coreTypes.index.getTopLevelProcedure(
'dart:js_interop_unsafe', 'JSObjectUnsafeUtilExtension|[]='),
_stringToJS = _typeEnvironment.coreTypes.index.getTopLevelProcedure(
@ -175,7 +175,7 @@ class ExportCreator extends Transformer {
Expression asJSObject(Expression object, [bool nullable = false]) =>
AsExpression(
object,
InterfaceType(_jsObject,
ExtensionType(_jsObject,
nullable ? Nullability.nullable : Nullability.nonNullable))
..fileOffset = node.fileOffset;
@ -192,7 +192,7 @@ class ExportCreator extends Transformer {
jsObject,
toJSString(methodName),
ListLiteral(args,
typeArgument: InterfaceType(_jsAny, Nullability.nullable))
typeArgument: ExtensionType(_jsAny, Nullability.nullable))
], types: [
returnType
]))
@ -211,7 +211,7 @@ class ExportCreator extends Transformer {
getObjectProperty(),
'create',
[asJSObject(proto ?? NullLiteral(), true)],
InterfaceType(_jsObject, Nullability.nonNullable));
ExtensionType(_jsObject, Nullability.nonNullable));
}
var exportMap =
@ -230,7 +230,7 @@ class ExportCreator extends Transformer {
var jsExporter = VariableDeclaration('#jsExporter',
initializer: getLiteral(proto),
type: InterfaceType(_jsObject, Nullability.nonNullable),
type: ExtensionType(_jsObject, Nullability.nonNullable),
isSynthesized: true)
..fileOffset = node.fileOffset
..parent = node.parent;
@ -295,7 +295,7 @@ class ExportCreator extends Transformer {
// statements for each export name.
var getSetMap = VariableDeclaration('#${exportName}Mapping',
initializer: getLiteral(),
type: InterfaceType(_jsObject, Nullability.nonNullable),
type: ExtensionType(_jsObject, Nullability.nonNullable),
isSynthesized: true)
..fileOffset = node.fileOffset
..parent = node.parent;

View file

@ -786,23 +786,27 @@ class ExtensionIndex {
///
/// This currently allows the interface type to be:
/// - all package:js classes
/// - dart:js_types types
/// - dart:js_interop types
/// - @Native types that implement JavaScriptObject
/// - extension types that wrap any of the above
bool isInteropExtensionType(ExtensionTypeDeclaration extensionType) {
final reference = extensionType.reference;
if (_interopExtensionTypeIndex.containsKey(reference)) {
return _interopExtensionTypeIndex[reference]!;
}
DartType repType = extensionType.declaredRepresentationType;
if (repType is ExtensionType) {
repType = repType.extensionTypeErasure;
// Check if this is an dart:js_interop JS type or recursively an extension
// type on one.
DartType repType = ExtensionType(extensionType, Nullability.nonNullable);
while (repType is ExtensionType) {
final declaration = repType.extensionTypeDeclaration;
if (declaration.enclosingLibrary.importUri.toString() ==
'dart:js_interop') {
return true;
}
repType = declaration.declaredRepresentationType;
}
if (repType is InterfaceType) {
final cls = repType.classNode;
// TODO(srujzs): Note that dart:_js_types types currently use a custom
// lowering of @staticInterop. Once
// https://github.com/dart-lang/sdk/issues/52687 is handled, we should
// modify this if-check to handle the new representation.
final javaScriptObject = _coreTypes.index
.tryGetClass('dart:_interceptors', 'JavaScriptObject');
if (hasStaticInteropAnnotation(cls) ||

View file

@ -13,112 +13,11 @@ import 'package:kernel/src/constant_replacer.dart';
import 'package:kernel/src/replacement_visitor.dart';
/// Erasure function for `@staticInterop` types for the JS compilers.
///
/// `dart:_js_types` are implemented currently using `@staticInterop`, but they
/// are erased to different types at runtime. Non-`dart:_js_types`
/// `@staticInterop` types are erased to `JavaScriptObject`.
InterfaceType eraseStaticInteropTypesForJSCompilers(
CoreTypes coreTypes, InterfaceType staticInteropType) {
if (staticInteropType.classNode.enclosingLibrary.importUri ==
Uri.parse('dart:_js_types')) {
final className = staticInteropType.classNode.name;
Class erasedClass;
var typeArguments = staticInteropType.typeArguments;
// TODO(srujzs): Switch to a switch expression once they're working in the
// SDK.
switch (className) {
case 'JSAny':
erasedClass = coreTypes.objectClass;
break;
case 'JSObject':
erasedClass =
coreTypes.index.getClass('dart:_interceptors', 'JSObject');
break;
case 'JSFunction':
erasedClass = coreTypes.functionClass;
break;
case 'JSExportedDartFunction':
erasedClass = coreTypes.functionClass;
break;
case 'JSArray':
erasedClass = coreTypes.listClass;
typeArguments = [coreTypes.objectNullableRawType];
break;
case 'JSBoxedDartObject':
erasedClass =
coreTypes.index.getClass('dart:_interceptors', 'JSObject');
break;
case 'JSArrayBuffer':
erasedClass = coreTypes.index.getClass('dart:typed_data', 'ByteBuffer');
break;
case 'JSDataView':
erasedClass = coreTypes.index.getClass('dart:typed_data', 'ByteData');
break;
case 'JSTypedArray':
erasedClass = coreTypes.index.getClass('dart:typed_data', 'TypedData');
break;
case 'JSInt8Array':
erasedClass = coreTypes.index.getClass('dart:typed_data', 'Int8List');
break;
case 'JSUint8Array':
erasedClass = coreTypes.index.getClass('dart:typed_data', 'Uint8List');
break;
case 'JSUint8ClampedArray':
erasedClass =
coreTypes.index.getClass('dart:typed_data', 'Uint8ClampedList');
break;
case 'JSInt16Array':
erasedClass = coreTypes.index.getClass('dart:typed_data', 'Int16List');
break;
case 'JSUint16Array':
erasedClass = coreTypes.index.getClass('dart:typed_data', 'Uint16List');
break;
case 'JSInt32Array':
erasedClass = coreTypes.index.getClass('dart:typed_data', 'Int32List');
break;
case 'JSUint32Array':
erasedClass = coreTypes.index.getClass('dart:typed_data', 'Uint32List');
break;
case 'JSFloat32Array':
erasedClass =
coreTypes.index.getClass('dart:typed_data', 'Float32List');
break;
case 'JSFloat64Array':
erasedClass =
coreTypes.index.getClass('dart:typed_data', 'Float64List');
break;
case 'JSNumber':
erasedClass = coreTypes.doubleClass;
break;
case 'JSBoolean':
erasedClass = coreTypes.boolClass;
break;
case 'JSString':
erasedClass = coreTypes.stringClass;
break;
case 'JSPromise':
erasedClass =
coreTypes.index.getClass('dart:_interceptors', 'JSObject');
break;
case 'JSSymbol':
erasedClass =
coreTypes.index.getClass('dart:_interceptors', 'JavaScriptSymbol');
break;
case 'JSBigInt':
erasedClass =
coreTypes.index.getClass('dart:_interceptors', 'JavaScriptBigInt');
break;
default:
throw 'Unimplemented `dart:_js_types`: $className';
}
return InterfaceType(
erasedClass, staticInteropType.declaredNullability, typeArguments);
} else {
return InterfaceType(
CoreTypes coreTypes, InterfaceType staticInteropType) =>
InterfaceType(
coreTypes.index.getClass('dart:_interceptors', 'JavaScriptObject'),
staticInteropType.declaredNullability);
}
}
class _TypeSubstitutor extends ReplacementVisitor {
final InterfaceType Function(InterfaceType staticInteropType)

View file

@ -168,9 +168,7 @@ void _doTransformsOnKernelLoad(
evaluationMode: options.useLegacySubtyping
? fe.EvaluationMode.weak
: fe.EvaluationMode.strong);
StaticInteropClassEraser(coreTypes,
additionalCoreLibraries: {'_js_types', 'js_interop'})
.visitComponent(component);
StaticInteropClassEraser(coreTypes).visitComponent(component);
globalTransforms.transformLibraries(
component.libraries, constantsEvaluator, coreTypes, options);
_simplifyConstConditionals(component, options, classHierarchy, reporter);

View file

@ -32,30 +32,6 @@ class JsInteropClass {
/*member: JsInteropClass.method:type=[
native:GenericClass<dynamic>,
native:JSAny,
native:JSArray,
native:JSArrayBuffer,
native:JSBigInt,
native:JSBoolean,
native:JSBoxedDartObject,
native:JSDataView,
native:JSExportedDartFunction,
native:JSFloat32Array,
native:JSFloat64Array,
native:JSFunction,
native:JSInt16Array,
native:JSInt32Array,
native:JSInt8Array,
native:JSNumber,
native:JSObject,
native:JSPromise,
native:JSString,
native:JSSymbol,
native:JSTypedArray,
native:JSUint16Array,
native:JSUint32Array,
native:JSUint8Array,
native:JSUint8ClampedArray,
native:JsInteropClass]*/
@JS()
external double method();

View file

@ -55,30 +55,6 @@ import 'package:js/js.dart';
native:DomError,
native:DomException,
native:ErrorEvent,
native:JSAny,
native:JSArray,
native:JSArrayBuffer,
native:JSBigInt,
native:JSBoolean,
native:JSBoxedDartObject,
native:JSDataView,
native:JSExportedDartFunction,
native:JSFloat32Array,
native:JSFloat64Array,
native:JSFunction,
native:JSInt16Array,
native:JSInt32Array,
native:JSInt8Array,
native:JSNumber,
native:JSObject,
native:JSPromise,
native:JSString,
native:JSSymbol,
native:JSTypedArray,
native:JSUint16Array,
native:JSUint32Array,
native:JSUint8Array,
native:JSUint8ClampedArray,
native:MediaError,
native:NavigatorUserMediaError,
native:OverconstrainedError,

View file

@ -62,30 +62,6 @@ import 'package:js/js.dart';
native:DomException,
native:ErrorEvent,
native:File,
native:JSAny,
native:JSArray,
native:JSArrayBuffer,
native:JSBigInt,
native:JSBoolean,
native:JSBoxedDartObject,
native:JSDataView,
native:JSExportedDartFunction,
native:JSFloat32Array,
native:JSFloat64Array,
native:JSFunction,
native:JSInt16Array,
native:JSInt32Array,
native:JSInt8Array,
native:JSNumber,
native:JSObject,
native:JSPromise,
native:JSString,
native:JSSymbol,
native:JSTypedArray,
native:JSUint16Array,
native:JSUint32Array,
native:JSUint8Array,
native:JSUint8ClampedArray,
native:MediaError,
native:NavigatorUserMediaError,
native:OverconstrainedError,

View file

@ -677,8 +677,6 @@ JsInteropStaticInteropTrustTypesUsedWithoutStaticInterop/analyzerCode: Fail # We
JsInteropStaticInteropTrustTypesUsedWithoutStaticInterop/example: Fail # Web compiler specific
JsInteropStaticInteropWithInstanceMembers/analyzerCode: Fail # Web compiler specific
JsInteropStaticInteropWithInstanceMembers/example: Fail # Web compiler specific
JsInteropStaticInteropWithInvalidJsTypesSupertype/analyzerCode: Fail # Web compiler specific
JsInteropStaticInteropWithInvalidJsTypesSupertype/example: Fail # Web compiler specific
JsInteropStaticInteropWithNonStaticSupertype/analyzerCode: Fail # Web compiler specific
JsInteropStaticInteropWithNonStaticSupertype/example: Fail # Web compiler specific
JsInteropStrictModeForbiddenLibrary/analyzerCode: Fail # Web compiler specific

View file

@ -5889,10 +5889,6 @@ JsInteropStaticInteropWithInstanceMembers:
problemMessage: "JS interop class '#name' with `@staticInterop` annotation cannot declare instance members."
correctionMessage: "Try moving the instance member to a static extension."
JsInteropStaticInteropWithInvalidJsTypesSupertype:
problemMessage: "`@staticInterop` class '#name' cannot have '#name2' as a supertype. `JSObject` and `JSAny` are the only valid supertypes from `dart:js_interop` for `@staticInterop` classes."
correctionMessage: "Try subtyping `JSObject` or `JSAny` instead, or try casting an object of type '#name' to '#name2' when needed."
JsInteropStaticInteropWithNonStaticSupertype:
problemMessage: "JS interop class '#name' has an `@staticInterop` annotation, but has supertype '#name2', which does not."
correctionMessage: "Try marking the supertype as a static interop class using `@staticInterop`."

View file

@ -5,11 +5,16 @@
import 'dart:_foreign_helper' as foreign_helper;
import 'dart:_interceptors' show JavaScriptObject;
import 'dart:_internal' show patch;
import 'dart:_js_helper' show staticInteropGlobalContext;
import 'dart:_js_helper' show createObjectLiteral, staticInteropGlobalContext;
import 'dart:_js_types';
import 'dart:js_interop';
import 'dart:js_util' as js_util;
import 'dart:typed_data';
@patch
JSObjectRepType _createObjectLiteral() =>
createObjectLiteral<JSObjectRepType>();
@patch
@pragma('dart2js:prefer-inline')
JSObject get globalContext => staticInteropGlobalContext as JSObject;

View file

@ -8,138 +8,70 @@
///
/// For consistency, all of the web backends have a version of this library.
///
/// For the time being, all JS types are erased to their respective Dart type at
/// runtime e.g. [JSString] -> [String]. Eventually, when we have inline
/// classes, we may choose to either:
///
/// 1. Use [Object] as the representation type.
/// 2. Have some analog to dart2wasm's [JSValue] as the representation type in
/// order to separate the Dart and JS type hierarchies at runtime.
/// 3. Continue using the respective Dart type.
///
/// Note that we can't use [Interceptor] to do option #2. [Interceptor] is a
/// supertype of types like [interceptors.JSString], but not a supertype of the
/// core types like [String]. This becomes relevant when we use external APIs.
/// External APIs get lowered to `js_util` calls, which cast the return value.
/// If a function returns a JavaScript string, it gets reified as a Dart
/// [String] for example. Then when we cast to [JSString] in `js_util`, we get
/// a cast failure, as [String] is not a subtype of [Interceptor].
///
/// For specific details of the JS type hierarchy, please see
/// `sdk/lib/js_interop/js_interop.dart`.
/// **WARNING**: You should *not* rely on these runtime types. Not only is this
/// library not guaranteed to be consistent across platforms, these types may
/// change in the future.
library _js_types;
import 'dart:_js_annotations';
import 'dart:_js_helper' show createObjectLiteral;
import 'dart:_native_typed_data' as typed_data;
import 'dart:_interceptors' as interceptors;
@JS()
@staticInterop
class JSAny {
// Unnamed factory constructor so users can only implement JSAny.
external factory JSAny._();
}
typedef JSAnyRepType = Object;
@JS()
@staticInterop
class JSObject implements JSAny {
/// Returns a new object literal.
factory JSObject() => createObjectLiteral<JSObject>();
}
typedef JSObjectRepType = interceptors.JSObject;
@JS()
@staticInterop
class JSFunction implements JSObject {}
// TODO(srujzs): The JS function types have to be typed as
// `LegacyJavaScriptObject` for now until we reify JS functions as
// `JavaScriptFunction` instead of `LegacyJavaScriptObject` in DDC. This will
// happen with the new RTI. Note that we *cannot* make this `Function`, even
// though all JS functions are Dart functions in our type system, because
// `Function` is not <: `JSObject`. This subtyping relationship is required for
// `dart:js_interop`'s extension types.
typedef JSFunctionRepType = interceptors.LegacyJavaScriptObject;
@JS()
@staticInterop
class JSExportedDartFunction implements JSFunction {}
typedef JSExportedDartFunctionRepType = interceptors.LegacyJavaScriptObject;
@JS('Array')
@staticInterop
class JSArray implements JSObject {
external factory JSArray();
external factory JSArray.withLength(int length);
}
typedef JSArrayRepType = interceptors.JSArray<Object?>;
@JS()
@staticInterop
class JSBoxedDartObject implements JSObject {}
typedef JSBoxedDartObjectRepType = interceptors.JSObject;
@JS()
@staticInterop
class JSArrayBuffer implements JSObject {}
typedef JSArrayBufferRepType = typed_data.NativeByteBuffer;
@JS()
@staticInterop
class JSDataView implements JSObject {}
typedef JSDataViewRepType = typed_data.NativeByteData;
@JS()
@staticInterop
class JSTypedArray implements JSObject {}
typedef JSTypedArrayRepType = typed_data.NativeTypedData;
@JS()
@staticInterop
class JSInt8Array implements JSTypedArray {}
typedef JSInt8ArrayRepType = typed_data.NativeInt8List;
@JS()
@staticInterop
class JSUint8Array implements JSTypedArray {}
typedef JSUint8ArrayRepType = typed_data.NativeUint8List;
@JS()
@staticInterop
class JSUint8ClampedArray implements JSTypedArray {}
typedef JSUint8ClampedArrayRepType = typed_data.NativeUint8ClampedList;
@JS()
@staticInterop
class JSInt16Array implements JSTypedArray {}
typedef JSInt16ArrayRepType = typed_data.NativeInt16List;
@JS()
@staticInterop
class JSUint16Array implements JSTypedArray {}
typedef JSUint16ArrayRepType = typed_data.NativeUint16List;
@JS()
@staticInterop
class JSInt32Array implements JSTypedArray {}
typedef JSInt32ArrayRepType = typed_data.NativeInt32List;
@JS()
@staticInterop
class JSUint32Array implements JSTypedArray {}
typedef JSUint32ArrayRepType = typed_data.NativeUint32List;
@JS()
@staticInterop
class JSFloat32Array implements JSTypedArray {}
typedef JSFloat32ArrayRepType = typed_data.NativeFloat32List;
@JS()
@staticInterop
class JSFloat64Array implements JSTypedArray {}
typedef JSFloat64ArrayRepType = typed_data.NativeFloat64List;
@JS()
@staticInterop
class JSNumber implements JSAny {}
typedef JSNumberRepType = double;
@JS()
@staticInterop
class JSBoolean implements JSAny {}
typedef JSBooleanRepType = bool;
@JS()
@staticInterop
class JSString implements JSAny {}
typedef JSStringRepType = String;
@JS()
@staticInterop
class JSSymbol implements JSAny {}
typedef JSPromiseRepType = interceptors.JSObject;
@JS()
@staticInterop
class JSBigInt implements JSAny {}
typedef JSSymbolRepType = interceptors.JavaScriptSymbol;
typedef JSBigIntRepType = interceptors.JavaScriptBigInt;
/// [JSVoid] is just a typedef for [void]. While we could just use
/// `JSUndefined`, in the future we may be able to use this to elide `return`s
/// in JS trampolines.
typedef JSVoid = void;
@JS('Promise')
@staticInterop
class JSPromise implements JSObject {
external factory JSPromise(JSFunction executor);
}
typedef JSVoidRepType = void;

View file

@ -18,6 +18,10 @@ import 'dart:typed_data';
/// TODO(joshualitt): Find a way to get rid of the explicit casts.
T _box<T>(WasmExternRef? ref) => JSValue(ref) as T;
@patch
js_types.JSObjectRepType _createObjectLiteral() =>
_box<js_types.JSObjectRepType>(js_helper.newObjectRaw());
// This should match the global context we use in our static interop lowerings.
@patch
JSObject get globalContext => js_util.globalThis as JSObject;

View file

@ -5,9 +5,10 @@
/// `dart:convert` UTF-8 decoding functions when the input is a JS typed array.
library dart._js_string_convert;
import "dart:_js_types";
import 'dart:_js_helper' as js;
import 'dart:_js_types';
import 'dart:_wasm';
import 'dart:js_interop';
/// Implements `_Utf8Decoder.convertSingle` hook for JS array inputs. Does not
/// do bounds checking.

View file

@ -4,8 +4,13 @@
/// This library exists to act as a uniform abstraction layer between the user
/// facing JS interop libraries and backend specific internal representations of
/// JS types. For consistency, all of the web backends have a version of this
/// library.
/// JS types.
///
/// For consistency, all of the web backends have a version of this library.
///
/// **WARNING**: You should *not* rely on these runtime types. Not only is this
/// library not guaranteed to be consistent across platforms, these types may
/// change in the future.
library dart._js_types;
import 'dart:_internal';
@ -21,154 +26,55 @@ part 'js_array.dart';
part 'js_string.dart';
part 'js_typed_array.dart';
/// Note that the semantics of JS types on Wasm backends are slightly different
/// from the JS backends. They all use `@staticInterop` currently, but Wasm
/// erases to [JSValue], while the JS backends erase each JS type to its
/// respective Dart type.
///
/// Because we're not sure exactly where things will end up, we're moving
/// gradually towards consistent semantics across all web backends. A gradual
/// path to consistent semantics might look something like:
/// 1) Launch MVP with JS backends conflating Dart types and JS types, and Wasm
/// backends implementing JS types with boxes. On Wasm backends, users will
/// have to explicitly coerce Dart types to JS types, possibly with some
/// overhead, whereas on JS backends users will get coercion for free. This
/// will enable some level of API sharing, without any additional performance
/// overhead on all backends.
/// 2) Introduce a flag for JS backends to support statically decoupling JS
/// types and Dart types on JS backends, while still allowing runtime
/// conflation. This will require users on JS backends to explicitly coerce
/// Dart types to JS types, but will not introduce additional runtime
/// overhead.
/// 3) Introduce a flag for JS backends to fully decouple JS types from Dart
/// types using boxes. However, we will be able to elide boxes on all
/// backends in many cases, except when JS types are upcast to [Object].
/// TODO(joshualitt): A number of issues are still TBD:
/// 1) Today Wasm backends must copy JS arrays to Dart [List]s and vice versa.
/// To match semantics, we have a few options.
/// a) Copy on JS backends, this will introduce overhead, but users can
/// always leave JS types as JS types to avoid the overhead.
/// b) Experiment with proxying. While we can proxy on the Dart side of the
/// interop boundary, we may not be able to do so on the JS side, and even
/// if we can it will involve considerable overhead and may be observable.
/// Furthermore, 'live' [List]s backed by native JS objects can be quite
/// confusing to users.
/// 2) There are many open questions around how to handle JSNull and
/// JSUndefined. For efficiency reasons, these are currently conflated on JS
/// backends, but this is not efficient on Wasm backends. We may encourage a
/// set of best practices, while allowing some divergence in behavior between
/// JS and Wasm backends until we have a better story here.
@JS()
@staticInterop
class JSAny {
// Unnamed factory constructor so users can only implement JSAny.
external factory JSAny._();
}
typedef JSAnyRepType = js.JSValue;
@JS('Object')
@staticInterop
class JSObject implements JSAny {
/// Returns a new object literal.
factory JSObject() => js.JSValue(js.newObjectRaw()) as JSObject;
typedef JSObjectRepType = js.JSValue;
/// Equivalent to `Object.keys(object)`.
external static JSArray keys(JSObject o);
}
typedef JSFunctionRepType = js.JSValue;
@JS()
@staticInterop
class JSFunction implements JSObject {}
typedef JSExportedDartFunctionRepType = js.JSValue;
@JS()
@staticInterop
class JSExportedDartFunction implements JSFunction {}
typedef JSArrayRepType = js.JSValue;
@JS('Promise')
@staticInterop
class JSPromise implements JSObject {
external factory JSPromise(JSFunction executor);
}
typedef JSBoxedDartObjectRepType = js.JSValue;
@JS('Array')
@staticInterop
class JSArray implements JSObject {
external factory JSArray();
external factory JSArray.withLength(int length);
}
typedef JSArrayBufferRepType = js.JSValue;
@JS()
@staticInterop
class JSBoxedDartObject implements JSObject {}
typedef JSDataViewRepType = js.JSValue;
@JS()
@staticInterop
class JSArrayBuffer implements JSObject {}
typedef JSTypedArrayRepType = js.JSValue;
@JS()
@staticInterop
class JSDataView implements JSObject {}
typedef JSInt8ArrayRepType = js.JSValue;
@JS()
@staticInterop
class JSTypedArray implements JSObject {}
typedef JSUint8ArrayRepType = js.JSValue;
@JS()
@staticInterop
class JSInt8Array implements JSTypedArray {}
typedef JSUint8ClampedArrayRepType = js.JSValue;
@JS()
@staticInterop
class JSUint8Array implements JSTypedArray {}
typedef JSInt16ArrayRepType = js.JSValue;
@JS()
@staticInterop
class JSUint8ClampedArray implements JSTypedArray {}
typedef JSUint16ArrayRepType = js.JSValue;
@JS()
@staticInterop
class JSInt16Array implements JSTypedArray {}
typedef JSInt32ArrayRepType = js.JSValue;
@JS()
@staticInterop
class JSUint16Array implements JSTypedArray {}
typedef JSUint32ArrayRepType = js.JSValue;
@JS()
@staticInterop
class JSInt32Array implements JSTypedArray {}
typedef JSFloat32ArrayRepType = js.JSValue;
@JS()
@staticInterop
class JSUint32Array implements JSTypedArray {}
typedef JSFloat64ArrayRepType = js.JSValue;
@JS()
@staticInterop
class JSFloat32Array implements JSTypedArray {}
typedef JSNumberRepType = js.JSValue;
@JS()
@staticInterop
class JSFloat64Array implements JSTypedArray {}
typedef JSBooleanRepType = js.JSValue;
@JS()
@staticInterop
class JSNumber implements JSAny {}
typedef JSStringRepType = js.JSValue;
@JS()
@staticInterop
class JSBoolean implements JSAny {}
typedef JSPromiseRepType = js.JSValue;
@JS()
@staticInterop
class JSString implements JSAny {}
typedef JSSymbolRepType = js.JSValue;
@JS()
@staticInterop
class JSSymbol implements JSAny {}
@JS()
@staticInterop
class JSBigInt implements JSAny {}
typedef JSBigIntRepType = js.JSValue;
/// [JSVoid] is just a typedef for [void]. While we could just use
/// `JSUndefined`, in the future we may be able to use this to elide `return`s
/// in JS trampolines.
typedef JSVoid = void;
typedef JSVoidRepType = void;

View file

@ -21,9 +21,15 @@ String quoteStringForRegExp(String string) =>
return stringToDartString(jsString);
}""", string);
// TODO(srujzs): Add this to `JSObject`.
@js.JS('Object.keys')
external JSArray objectKeys(JSObject o);
// TODO(srujzs): Convert these to extension types and have `JSNativeMatch`
// subtype `JSArray`.
@js.JS()
@js.staticInterop
class JSNativeMatch extends JSArray {
class JSNativeMatch {
// This constructor exists just to avoid the `no unnamed constructor` error.
external factory JSNativeMatch();
}
@ -33,6 +39,8 @@ extension JSNativeMatchExtension on JSNativeMatch {
external JSNumber get index;
external JSObject? get groups;
external JSNumber get length;
external JSAny? pop();
external JSAny? operator [](JSNumber index);
}
@js.JS()
@ -115,8 +123,7 @@ class JSSyntaxRegExp implements RegExp {
RegExpMatch? firstMatch(String string) {
JSNativeMatch? m = _nativeRegExp.exec(string.toJS);
if (m.isUndefinedOrNull) return null;
return new _MatchImplementation(this, m!);
return m == null ? null : new _MatchImplementation(this, m);
}
bool hasMatch(String string) {
@ -140,18 +147,17 @@ class JSSyntaxRegExp implements RegExp {
JSNativeRegExp regexp = _nativeGlobalVersion;
regexp.lastIndex = start.toJS;
JSNativeMatch? match = regexp.exec(string.toJS);
if (match.isUndefinedOrNull) return null;
return new _MatchImplementation(this, match!);
return match == null ? null : new _MatchImplementation(this, match);
}
RegExpMatch? _execAnchored(String string, int start) {
JSNativeRegExp regexp = _nativeAnchoredVersion;
regexp.lastIndex = start.toJS;
JSNativeMatch? match = regexp.exec(string.toJS);
if (match.isUndefinedOrNull) return null;
if (match == null) return null;
// If the last capture group participated, the original regexp did not
// match at the start position.
if (match!.pop() != null) return null;
if (match.pop() != null) return null;
return new _MatchImplementation(this, match);
}
@ -201,8 +207,8 @@ class _MatchImplementation implements RegExpMatch {
String? namedGroup(String name) {
JSObject? groups = _match.groups;
if (groups.isDefinedAndNotNull) {
Object? result = dartifyRaw(groups![name].toExternRef);
if (groups != null) {
Object? result = dartifyRaw(groups[name].toExternRef);
if (result != null ||
hasPropertyRaw(groups.toExternRef, name.toExternRef)) {
return result?.toString();
@ -213,8 +219,8 @@ class _MatchImplementation implements RegExpMatch {
Iterable<String> get groupNames {
JSObject? groups = _match.groups;
if (groups.isDefinedAndNotNull) {
return JSArrayIterableAdapter<String>(JSObject.keys(groups!));
if (groups != null) {
return JSArrayIterableAdapter<String>(objectKeys(groups));
}
return Iterable.empty();
}

View file

@ -2,13 +2,13 @@
// 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.
import "dart:_internal" show ClassID, patch, POWERS_OF_TEN, unsafeCast;
import "dart:_js_string_convert";
import "dart:_js_types";
import 'dart:_internal' show ClassID, patch, POWERS_OF_TEN, unsafeCast;
import 'dart:_js_helper' as js;
import 'dart:_js_string_convert';
import 'dart:_js_types';
import 'dart:_wasm';
import "dart:typed_data" show Uint8List, Uint16List;
import 'dart:js_interop';
import 'dart:typed_data' show Uint8List, Uint16List;
@patch
dynamic _parseJson(

View file

@ -6,10 +6,10 @@
/// interop with JS. The JS type hierarchy is modeled after the actual type
/// hierarchy in JS, and not the Dart type hierarchy.
///
/// Note: The JS types that are exposed through this library are currently
/// wrapper types that are erased to their runtime types. The runtime types will
/// differ based on the backend. In general, stick to using conversion functions
/// that are exposed as extension methods e.g. 'toJS'.
/// Note: The JS types defined in this library only provide static guarantees.
/// The runtime types differ based on the backend, so rely on static
/// functionality like the conversion functions e.g. `toJS` and not runtime
/// mechanisms like type checks and casts.
///
/// **WARNING**:
/// This library is still a work in progress. As such, JS types, allowed syntax,
@ -19,7 +19,7 @@
/// {@category Web}
library dart.js_interop;
import 'dart:_js_types' as js_types;
import 'dart:_js_types';
import 'dart:js_interop_unsafe';
import 'dart:typed_data';
@ -57,91 +57,134 @@ class JS {
/// These are meant to separate the Dart and JS type hierarchies statically.
///
/// **WARNING**:
/// For now, the runtime semantics between backends may differ and may not be
/// intuitive e.g. casting to [JSString] may give you inconsistent and
/// surprising results depending on the value. It is preferred to always use the
/// conversion functions e.g. `toJS` and `toDart`. The only runtime semantics
/// stability we can guarantee is if a value actually is the JS type you are
/// type-checking with/casting to e.g. `obj as JSString` will continue to work
/// if `obj` actually is a JavaScript string.
/// The runtime semantics between backends differ and may not be intuitive e.g.
/// casting to [JSString] may give you inconsistent and surprising results
/// depending on the value and the backend. It is preferred to always use the
/// conversion functions e.g. `toJS` and `toDart`. You should always use interop
/// to type-check e.g. `typeofEquals` and `instanceOfString` instead of relying
/// on `is` and `as`, as the latter is backend-dependent.
/// The overall top type in the JS types hierarchy.
typedef JSAny = js_types.JSAny;
extension type JSAny._(JSAnyRepType _jsAny) implements Object {}
/// The representation type of all JavaScript objects for inline classes,
/// [JSObject] <: [JSAny].
/// The representation type of all JavaScript objects for extension types.
///
/// This is the supertype of all JS objects, but not other JS types, like
/// primitives. This is the only allowed `on` type for inline classes written by
/// users to model JS interop objects. See https://dart.dev/web/js-interop for
/// more details on how to use JS interop.
// TODO(srujzs): This class _must_ be sealed before we can make this library
// public. Either use the CFE mechanisms that exist today, or use the Dart 3
// sealed classes feature.
// TODO(joshualitt): Do we need to seal any other JS types on JS backends? We
// probably want to seal all JS types on Wasm backends.
// TODO(joshualitt): Add a [JSObject] constructor.
typedef JSObject = js_types.JSObject;
/// primitives. See https://dart.dev/web/js-interop for more details on how to
/// use JS interop.
extension type JSObject._(JSObjectRepType _jsObject) implements JSAny {
/// Constructor to go from an object from previous interop, like the types
/// from `package:js` or `dart:html`, to [JSObject].
///
/// This and the public representation field are intended to avoid users
/// having to cast to and from [JSObject].
JSObject.fromInteropObject(Object interopObject)
: _jsObject = interopObject as JSObjectRepType;
/// The type of all JS functions, [JSFunction] <: [JSObject].
typedef JSFunction = js_types.JSFunction;
/// Returns a new object literal.
JSObject() : _jsObject = _createObjectLiteral();
}
// TODO(srujzs): Move this to `JSObject` once we can patch extension type
// members.
external JSObjectRepType _createObjectLiteral();
/// The type of all JS functions.
extension type JSFunction._(JSFunctionRepType _jsFunction)
implements JSObject {}
/// The type of all Dart functions adapted to be callable from JS. We only allow
/// a subset of Dart functions to be callable from JS, [JSExportedDartFunction]
/// <: [JSFunction].
/// a subset of Dart functions to be callable from JS.
// TODO(joshualitt): Detail exactly what are the requirements.
typedef JSExportedDartFunction = js_types.JSExportedDartFunction;
extension type JSExportedDartFunction._(
JSExportedDartFunctionRepType _jsExportedDartFunction)
implements JSFunction {}
/// The type of JS promises and promise-like objects, [JSPromise] <: [JSObject].
typedef JSPromise = js_types.JSPromise;
/// The type of JS promises and promise-like objects.
@JS('Promise')
extension type JSPromise._(JSPromiseRepType _jsPromise) implements JSObject {
external JSPromise(JSFunction executor);
}
/// The type of all JS arrays, [JSArray] <: [JSObject].
typedef JSArray = js_types.JSArray;
/// The type of all JS arrays.
@JS('Array')
extension type JSArray._(JSArrayRepType _jsArray) implements JSObject {
external JSArray();
external JSArray.withLength(int length);
}
/// The type of the boxed Dart object that can be passed to JS safely. There is
/// no interface specified of this boxed object, and you may get a new box each
/// time you box the same Dart object.
/// [JSBoxedDartObject] <: [JSObject].
typedef JSBoxedDartObject = js_types.JSBoxedDartObject;
extension type JSBoxedDartObject._(JSBoxedDartObjectRepType _jsBoxedDartObject)
implements JSObject {}
/// The type of JS array buffers, [JSArrayBuffer] <: [JSObject].
typedef JSArrayBuffer = js_types.JSArrayBuffer;
/// The type of JS' `ArrayBuffer`.
extension type JSArrayBuffer._(JSArrayBufferRepType _jsArrayBuffer)
implements JSObject {}
/// The type of JS byte data, [JSDataView] <: [JSObject].
typedef JSDataView = js_types.JSDataView;
/// The type of JS' `DataView`.
extension type JSDataView._(JSDataViewRepType _jsDataView)
implements JSObject {}
/// The abstract supertype of all JS typed arrays, [JSTypedArray] <: [JSObject].
typedef JSTypedArray = js_types.JSTypedArray;
/// The abstract supertype of all JS typed arrays.
extension type JSTypedArray._(JSTypedArrayRepType _jsTypedArray)
implements JSObject {}
/// The typed arrays themselves, `*Array` <: [JSTypedArray].
typedef JSInt8Array = js_types.JSInt8Array;
typedef JSUint8Array = js_types.JSUint8Array;
typedef JSUint8ClampedArray = js_types.JSUint8ClampedArray;
typedef JSInt16Array = js_types.JSInt16Array;
typedef JSUint16Array = js_types.JSUint16Array;
typedef JSInt32Array = js_types.JSInt32Array;
typedef JSUint32Array = js_types.JSUint32Array;
typedef JSFloat32Array = js_types.JSFloat32Array;
typedef JSFloat64Array = js_types.JSFloat64Array;
/// The type of JS' `Int8Array`.
extension type JSInt8Array._(JSInt8ArrayRepType _jsInt8Array)
implements JSTypedArray {}
/// The type of JS' `Uint8Array`.
extension type JSUint8Array._(JSUint8ArrayRepType _jsUint8Array)
implements JSTypedArray {}
/// The type of JS' `Uint8ClampedArray`.
extension type JSUint8ClampedArray._(
JSUint8ClampedArrayRepType _jsUint8ClampedArray) implements JSTypedArray {}
/// The type of JS' `Int16Array`.
extension type JSInt16Array._(JSInt16ArrayRepType _jsInt16Array)
implements JSTypedArray {}
/// The type of JS' `Uint16Array`.
extension type JSUint16Array._(JSUint16ArrayRepType _jsUint16Array)
implements JSTypedArray {}
/// The type of JS' `Int32Array`.
extension type JSInt32Array._(JSInt32ArrayRepType _jsInt32Array)
implements JSTypedArray {}
/// The type of JS' `Uint32Array`.
extension type JSUint32Array._(JSUint32ArrayRepType _jsUint32Array)
implements JSTypedArray {}
/// The type of JS' `Float32Array`.
extension type JSFloat32Array._(JSFloat32ArrayRepType _jsFloat32Array)
implements JSTypedArray {}
/// The type of JS' `Float64Array`.
extension type JSFloat64Array._(JSFloat64ArrayRepType _jsFloat64Array)
implements JSTypedArray {}
// The various JS primitive types. Crucially, unlike the Dart type hierarchy,
// none of these are subtypes of [JSObject], but rather they are logically
// subtypes of [JSAny].
/// The type of JS numbers, [JSNumber] <: [JSAny].
typedef JSNumber = js_types.JSNumber;
/// The type of JS numbers.
extension type JSNumber._(JSNumberRepType _jsNumber) implements JSAny {}
/// The type of JS booleans, [JSBoolean] <: [JSAny].
typedef JSBoolean = js_types.JSBoolean;
/// The type of JS booleans.
extension type JSBoolean._(JSBooleanRepType _jsBoolean) implements JSAny {}
/// The type of JS strings, [JSString] <: [JSAny].
typedef JSString = js_types.JSString;
/// The type of JS strings.
extension type JSString._(JSStringRepType _jsString) implements JSAny {}
/// The type of JS Symbols, [JSSymbol] <: [JSAny].
typedef JSSymbol = js_types.JSSymbol;
/// The type of JS `Symbol`s.
extension type JSSymbol._(JSSymbolRepType _jsSymbol) implements JSAny {}
/// The type of JS BigInts, [JSBigInt] <: [JSAny].
typedef JSBigInt = js_types.JSBigInt;
/// The type of JS `BigInt`s.
extension type JSBigInt._(JSBigIntRepType _jsBigInt) implements JSAny {}
/// A getter to retrieve the global context that is used in static interop
/// lowering.
@ -207,11 +250,13 @@ extension JSObjectUtilExtension on JSObject {
/// The type of `JSUndefined` when returned from functions. Unlike pure JS,
/// no actual object will be returned.
typedef JSVoid = js_types.JSVoid;
// TODO(srujzs): Should we just remove this? There are no performance costs from
// using `void`, and we'll likely provide a different way to box `undefined`.
typedef JSVoid = JSVoidRepType;
// Extension members to support conversions between Dart types and JS types.
// Not all Dart types can be converted to JS types and vice versa.
// TODO(joshualitt): We might want to investigate using inline classes instead
// TODO(joshualitt): We might want to investigate using extension types instead
// of extension methods for these methods.
/// [JSExportedDartFunction] <-> [Function]

View file

@ -79,6 +79,7 @@ extension type EExtensionType(EJSObject _) {}
@JS()
extension type EExtensionType2(EExtensionType _) {}
@JS()
extension type ENonInterop._(EObject _) {
// ^

View file

@ -1,279 +0,0 @@
// Copyright (c) 2023, 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 subtype_js_types_static_test;
import 'dart:js_interop';
@JS()
@staticInterop
class ExtendsJSAny extends JSAny {}
// ^
// [web] The superclass, 'JSAny', has no unnamed constructor that takes no arguments.
// ^^^^^
// [analyzer] COMPILE_TIME_ERROR.NO_GENERATIVE_CONSTRUCTORS_IN_SUPERCLASS
@JS()
@staticInterop
class ImplementsJSAny implements JSAny {}
@JS()
@staticInterop
class ExtendsJSObject extends JSObject {}
// ^
// [web] The superclass, 'JSObject', has no unnamed constructor that takes no arguments.
// ^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.NO_GENERATIVE_CONSTRUCTORS_IN_SUPERCLASS
@JS()
@staticInterop
class ImplementsJSObject implements JSObject {}
@JS()
@staticInterop
class ExtendsJSFunction extends JSFunction {}
// ^
// [web] `@staticInterop` class 'ExtendsJSFunction' cannot have 'JSFunction' as a supertype. `JSObject` and `JSAny` are the only valid supertypes from `dart:js_interop` for `@staticInterop` classes.
@JS()
@staticInterop
class ImplementsJSFunction implements JSFunction {}
// ^
// [web] `@staticInterop` class 'ImplementsJSFunction' cannot have 'JSFunction' as a supertype. `JSObject` and `JSAny` are the only valid supertypes from `dart:js_interop` for `@staticInterop` classes.
@JS()
@staticInterop
class ExtendsJSExportedDartFunction extends JSExportedDartFunction {}
// ^
// [web] `@staticInterop` class 'ExtendsJSExportedDartFunction' cannot have 'JSExportedDartFunction' as a supertype. `JSObject` and `JSAny` are the only valid supertypes from `dart:js_interop` for `@staticInterop` classes.
@JS()
@staticInterop
class ImplementsJSExportedDartFunction implements JSExportedDartFunction {}
// ^
// [web] `@staticInterop` class 'ImplementsJSExportedDartFunction' cannot have 'JSExportedDartFunction' as a supertype. `JSObject` and `JSAny` are the only valid supertypes from `dart:js_interop` for `@staticInterop` classes.
@JS()
@staticInterop
class ExtendsJSArray extends JSArray {
// ^
// [web] `@staticInterop` class 'ExtendsJSArray' cannot have 'JSArray' as a supertype. `JSObject` and `JSAny` are the only valid supertypes from `dart:js_interop` for `@staticInterop` classes.
// Silence error about extending class with only factories.
external factory ExtendsJSArray();
}
@JS()
@staticInterop
class ImplementsJSArray implements JSArray {}
// ^
// [web] `@staticInterop` class 'ImplementsJSArray' cannot have 'JSArray' as a supertype. `JSObject` and `JSAny` are the only valid supertypes from `dart:js_interop` for `@staticInterop` classes.
@JS()
@staticInterop
class ExtendsJSBoxedDartObject extends JSBoxedDartObject {}
// ^
// [web] `@staticInterop` class 'ExtendsJSBoxedDartObject' cannot have 'JSBoxedDartObject' as a supertype. `JSObject` and `JSAny` are the only valid supertypes from `dart:js_interop` for `@staticInterop` classes.
@JS()
@staticInterop
class ImplementsJSBoxedDartObject implements JSBoxedDartObject {}
// ^
// [web] `@staticInterop` class 'ImplementsJSBoxedDartObject' cannot have 'JSBoxedDartObject' as a supertype. `JSObject` and `JSAny` are the only valid supertypes from `dart:js_interop` for `@staticInterop` classes.
@JS()
@staticInterop
class ExtendsJSArrayBuffer extends JSArrayBuffer {}
// ^
// [web] `@staticInterop` class 'ExtendsJSArrayBuffer' cannot have 'JSArrayBuffer' as a supertype. `JSObject` and `JSAny` are the only valid supertypes from `dart:js_interop` for `@staticInterop` classes.
@JS()
@staticInterop
class ImplementsJSArrayBuffer implements JSArrayBuffer {}
// ^
// [web] `@staticInterop` class 'ImplementsJSArrayBuffer' cannot have 'JSArrayBuffer' as a supertype. `JSObject` and `JSAny` are the only valid supertypes from `dart:js_interop` for `@staticInterop` classes.
@JS()
@staticInterop
class ExtendsJSDataView extends JSDataView {}
// ^
// [web] `@staticInterop` class 'ExtendsJSDataView' cannot have 'JSDataView' as a supertype. `JSObject` and `JSAny` are the only valid supertypes from `dart:js_interop` for `@staticInterop` classes.
@JS()
@staticInterop
class ImplementsJSDataView implements JSDataView {}
// ^
// [web] `@staticInterop` class 'ImplementsJSDataView' cannot have 'JSDataView' as a supertype. `JSObject` and `JSAny` are the only valid supertypes from `dart:js_interop` for `@staticInterop` classes.
@JS()
@staticInterop
class ExtendsJSTypedArray extends JSTypedArray {}
// ^
// [web] `@staticInterop` class 'ExtendsJSTypedArray' cannot have 'JSTypedArray' as a supertype. `JSObject` and `JSAny` are the only valid supertypes from `dart:js_interop` for `@staticInterop` classes.
@JS()
@staticInterop
class ImplementsJSTypedArray implements JSTypedArray {}
// ^
// [web] `@staticInterop` class 'ImplementsJSTypedArray' cannot have 'JSTypedArray' as a supertype. `JSObject` and `JSAny` are the only valid supertypes from `dart:js_interop` for `@staticInterop` classes.
@JS()
@staticInterop
class ExtendsJSInt8Array extends JSInt8Array {}
// ^
// [web] `@staticInterop` class 'ExtendsJSInt8Array' cannot have 'JSInt8Array' as a supertype. `JSObject` and `JSAny` are the only valid supertypes from `dart:js_interop` for `@staticInterop` classes.
@JS()
@staticInterop
class ImplementsJSInt8Array implements JSInt8Array {}
// ^
// [web] `@staticInterop` class 'ImplementsJSInt8Array' cannot have 'JSInt8Array' as a supertype. `JSObject` and `JSAny` are the only valid supertypes from `dart:js_interop` for `@staticInterop` classes.
@JS()
@staticInterop
class ExtendsJSUint8Array extends JSUint8Array {}
// ^
// [web] `@staticInterop` class 'ExtendsJSUint8Array' cannot have 'JSUint8Array' as a supertype. `JSObject` and `JSAny` are the only valid supertypes from `dart:js_interop` for `@staticInterop` classes.
@JS()
@staticInterop
class ImplementsJSUint8Array implements JSUint8Array {}
// ^
// [web] `@staticInterop` class 'ImplementsJSUint8Array' cannot have 'JSUint8Array' as a supertype. `JSObject` and `JSAny` are the only valid supertypes from `dart:js_interop` for `@staticInterop` classes.
@JS()
@staticInterop
class ExtendsJSUint8ClampedArray extends JSUint8ClampedArray {}
// ^
// [web] `@staticInterop` class 'ExtendsJSUint8ClampedArray' cannot have 'JSUint8ClampedArray' as a supertype. `JSObject` and `JSAny` are the only valid supertypes from `dart:js_interop` for `@staticInterop` classes.
@JS()
@staticInterop
class ImplementsJSUint8ClampedArray implements JSUint8ClampedArray {}
// ^
// [web] `@staticInterop` class 'ImplementsJSUint8ClampedArray' cannot have 'JSUint8ClampedArray' as a supertype. `JSObject` and `JSAny` are the only valid supertypes from `dart:js_interop` for `@staticInterop` classes.
@JS()
@staticInterop
class ExtendsJSInt16Array extends JSInt16Array {}
// ^
// [web] `@staticInterop` class 'ExtendsJSInt16Array' cannot have 'JSInt16Array' as a supertype. `JSObject` and `JSAny` are the only valid supertypes from `dart:js_interop` for `@staticInterop` classes.
@JS()
@staticInterop
class ImplementsJSInt16Array implements JSInt16Array {}
// ^
// [web] `@staticInterop` class 'ImplementsJSInt16Array' cannot have 'JSInt16Array' as a supertype. `JSObject` and `JSAny` are the only valid supertypes from `dart:js_interop` for `@staticInterop` classes.
@JS()
@staticInterop
class ExtendsJSUint16Array extends JSUint16Array {}
// ^
// [web] `@staticInterop` class 'ExtendsJSUint16Array' cannot have 'JSUint16Array' as a supertype. `JSObject` and `JSAny` are the only valid supertypes from `dart:js_interop` for `@staticInterop` classes.
@JS()
@staticInterop
class ImplementsJSUint16Array implements JSUint16Array {}
// ^
// [web] `@staticInterop` class 'ImplementsJSUint16Array' cannot have 'JSUint16Array' as a supertype. `JSObject` and `JSAny` are the only valid supertypes from `dart:js_interop` for `@staticInterop` classes.
@JS()
@staticInterop
class ExtendsJSInt32Array extends JSInt32Array {}
// ^
// [web] `@staticInterop` class 'ExtendsJSInt32Array' cannot have 'JSInt32Array' as a supertype. `JSObject` and `JSAny` are the only valid supertypes from `dart:js_interop` for `@staticInterop` classes.
@JS()
@staticInterop
class ImplementsJSInt32Array implements JSInt32Array {}
// ^
// [web] `@staticInterop` class 'ImplementsJSInt32Array' cannot have 'JSInt32Array' as a supertype. `JSObject` and `JSAny` are the only valid supertypes from `dart:js_interop` for `@staticInterop` classes.
@JS()
@staticInterop
class ExtendsJSUint32Array extends JSUint32Array {}
// ^
// [web] `@staticInterop` class 'ExtendsJSUint32Array' cannot have 'JSUint32Array' as a supertype. `JSObject` and `JSAny` are the only valid supertypes from `dart:js_interop` for `@staticInterop` classes.
@JS()
@staticInterop
class ImplementsJSUint32Array implements JSUint32Array {}
// ^
// [web] `@staticInterop` class 'ImplementsJSUint32Array' cannot have 'JSUint32Array' as a supertype. `JSObject` and `JSAny` are the only valid supertypes from `dart:js_interop` for `@staticInterop` classes.
@JS()
@staticInterop
class ExtendsJSFloat32Array extends JSFloat32Array {}
// ^
// [web] `@staticInterop` class 'ExtendsJSFloat32Array' cannot have 'JSFloat32Array' as a supertype. `JSObject` and `JSAny` are the only valid supertypes from `dart:js_interop` for `@staticInterop` classes.
@JS()
@staticInterop
class ImplementsJSFloat32Array implements JSFloat32Array {}
// ^
// [web] `@staticInterop` class 'ImplementsJSFloat32Array' cannot have 'JSFloat32Array' as a supertype. `JSObject` and `JSAny` are the only valid supertypes from `dart:js_interop` for `@staticInterop` classes.
@JS()
@staticInterop
class ExtendsJSFloat64Array extends JSFloat64Array {}
// ^
// [web] `@staticInterop` class 'ExtendsJSFloat64Array' cannot have 'JSFloat64Array' as a supertype. `JSObject` and `JSAny` are the only valid supertypes from `dart:js_interop` for `@staticInterop` classes.
@JS()
@staticInterop
class ImplementsJSFloat64Array implements JSFloat64Array {}
// ^
// [web] `@staticInterop` class 'ImplementsJSFloat64Array' cannot have 'JSFloat64Array' as a supertype. `JSObject` and `JSAny` are the only valid supertypes from `dart:js_interop` for `@staticInterop` classes.
@JS()
@staticInterop
class ExtendsJSNumber extends JSNumber {}
// ^
// [web] `@staticInterop` class 'ExtendsJSNumber' cannot have 'JSNumber' as a supertype. `JSObject` and `JSAny` are the only valid supertypes from `dart:js_interop` for `@staticInterop` classes.
@JS()
@staticInterop
class ImplementsJSNumber implements JSNumber {}
// ^
// [web] `@staticInterop` class 'ImplementsJSNumber' cannot have 'JSNumber' as a supertype. `JSObject` and `JSAny` are the only valid supertypes from `dart:js_interop` for `@staticInterop` classes.
@JS()
@staticInterop
class ExtendsJSBoolean extends JSBoolean {}
// ^
// [web] `@staticInterop` class 'ExtendsJSBoolean' cannot have 'JSBoolean' as a supertype. `JSObject` and `JSAny` are the only valid supertypes from `dart:js_interop` for `@staticInterop` classes.
@JS()
@staticInterop
class ImplementsJSBoolean implements JSBoolean {}
// ^
// [web] `@staticInterop` class 'ImplementsJSBoolean' cannot have 'JSBoolean' as a supertype. `JSObject` and `JSAny` are the only valid supertypes from `dart:js_interop` for `@staticInterop` classes.
@JS()
@staticInterop
class ExtendsJSString extends JSString {}
// ^
// [web] `@staticInterop` class 'ExtendsJSString' cannot have 'JSString' as a supertype. `JSObject` and `JSAny` are the only valid supertypes from `dart:js_interop` for `@staticInterop` classes.
@JS()
@staticInterop
class ImplementsJSString implements JSString {}
// ^
// [web] `@staticInterop` class 'ImplementsJSString' cannot have 'JSString' as a supertype. `JSObject` and `JSAny` are the only valid supertypes from `dart:js_interop` for `@staticInterop` classes.
@JS()
@staticInterop
class ExtendsJSPromise extends JSPromise {}
// ^
// [web] The superclass, 'JSPromise', has no unnamed constructor that takes no arguments.
// [web] `@staticInterop` class 'ExtendsJSPromise' cannot have 'JSPromise' as a supertype. `JSObject` and `JSAny` are the only valid supertypes from `dart:js_interop` for `@staticInterop` classes.
// ^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.NO_GENERATIVE_CONSTRUCTORS_IN_SUPERCLASS
@JS()
@staticInterop
class ImplementsJSPromise implements JSPromise {}
// ^
// [web] `@staticInterop` class 'ImplementsJSPromise' cannot have 'JSPromise' as a supertype. `JSObject` and `JSAny` are the only valid supertypes from `dart:js_interop` for `@staticInterop` classes.

View file

@ -14,8 +14,8 @@ fix_data_tests/*: SkipByDesign
html/*: SkipByDesign # dart:html not supported on dart2wasm
isolate/*: SkipByDesign
js/(?!export|static_interop_test)*: SkipByDesign
js/static_interop_test/extension_type/non_interop_extension_type_static_test: SkipByDesign # Some external checks are not run on dart2wasm.
js/static_interop_test/external_static_member_lowerings_trusttypes_test: SkipByDesign # Tests @trustTypes, which is unsupported on dart2wasm.
js/static_interop_test/inline_class/non_interop_inline_class_static_test: SkipByDesign # Some external checks are not run on dart2wasm.
js/static_interop_test/static_external_extension_members_static_test: SkipByDesign # dart:html not supported on dart2wasm.
js/static_interop_test/top_level_member_annotation_static_test: SkipByDesign # Some external checks are not run on dart2wasm.
mirrors/*: SkipByDesign
@ -72,14 +72,14 @@ js/js_util/properties_test: SkipByDesign # Issue 42085. CSP policy disallows inj
js/method_call_on_object_test: SkipByDesign # Issue 42085.
js/mock_test/*: SkipByDesign # Issue 42085.
js/parameters_test: SkipByDesign # Issue 42085.
js/static_interop_test/extension_type/external_extension_member_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
js/static_interop_test/extension_type/external_member_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
js/static_interop_test/extension_type/external_static_member_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
js/static_interop_test/extension_type/external_static_member_with_namespaces_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
js/static_interop_test/external_extension_members_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
js/static_interop_test/external_static_member_lowerings_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
js/static_interop_test/external_static_member_lowerings_trusttypes_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
js/static_interop_test/external_static_member_lowerings_with_namespaces_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
js/static_interop_test/inline_class/external_extension_member_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
js/static_interop_test/inline_class/external_member_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
js/static_interop_test/inline_class/external_static_member_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
js/static_interop_test/inline_class/external_static_member_with_namespaces_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
js/static_interop_test/js_array_proxy_or_ref_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
js/static_interop_test/js_array_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
js/static_interop_test/js_function_conversions_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code