| // Copyright (c) 2025, 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. | |
| import 'dart:js_interop'; | |
| // You can either have a @JSExport annotation on the entire class or select | |
| // members only, and they may contain members that are ignored. | |
| @JSExport() | |
| class ExportAll { | |
| int field = throw ''; | |
| final int finalField = throw ''; | |
| int get getSet => throw ''; | |
| set getSet(int val) => throw ''; | |
| int method() => throw ''; | |
| } | |
| class ExportSome { | |
| ExportSome(); | |
| factory ExportSome.factory() => ExportSome(); | |
| @JSExport() | |
| int field = throw ''; | |
| final int finalField = throw ''; | |
| @JSExport() | |
| int get getSet => throw ''; | |
| set getSet(int val) => throw ''; | |
| @JSExport() | |
| int method() => throw ''; | |
| static int staticField = throw ''; | |
| static void staticMethod() => throw ''; | |
| } | |
| extension on ExportSome { | |
| int extensionMethod() => throw ''; | |
| static int extensionStaticField = throw ''; | |
| static void extensionStaticMethod() => throw ''; | |
| } | |
| // We should leave Dart classes with no exports alone unless used in | |
| // `createDartExport`. | |
| class NoAnnotations { | |
| int field = throw ''; | |
| final int finalField = throw ''; | |
| int get getSet => throw ''; | |
| set getSet(int val) => throw ''; | |
| int method() => throw ''; | |
| } | |
| // If there is a `@JSExport` annotation, but no exportable members, it's | |
| // considered an error. | |
| @JSExport() | |
| abstract class ExportNoneQualify { | |
| // ^ | |
| // [web] Class 'ExportNoneQualify' has no exportable members in the class or the inheritance chain. | |
| factory ExportNoneQualify() => throw ''; | |
| abstract int abstractField; | |
| void abstractMethod(); | |
| static int staticField = throw ''; | |
| static void staticMethod() => throw ''; | |
| } | |
| extension on ExportNoneQualify { | |
| int method() => throw ''; | |
| static int staticField = throw ''; | |
| static void staticMethod() => throw ''; | |
| } | |
| @JSExport() | |
| class ExportEmpty {} | |
| // ^ | |
| // [web] Class 'ExportEmpty' has no exportable members in the class or the inheritance chain. | |
| // These are errors, as there are no exportable members that have the annotation | |
| // on them or on their class. | |
| @JSExport() | |
| class ExportWithNoExportSuperclass extends NoAnnotations {} | |
| // ^ | |
| // [web] Class 'ExportWithNoExportSuperclass' has no exportable members in the class or the inheritance chain. | |
| @JSExport() | |
| class ExportWithEmptyExportSuperclass extends ExportEmpty {} | |
| // ^ | |
| // [web] Class 'ExportWithEmptyExportSuperclass' has no exportable members in the class or the inheritance chain. | |
| // This isn't an error to write, but it will be when you use it as part of | |
| // `createDartExport`. | |
| class NoExportWithExportSuperclass extends ExportAll {} | |
| @JS() | |
| @staticInterop | |
| class StaticInterop { | |
| external factory StaticInterop(); | |
| } | |
| typedef InvalidType = void Function(); | |
| // Incompatible members can't have the same export name using renaming. | |
| @JSExport() | |
| class RenameCollision { | |
| // ^ | |
| // [web] The following class members collide with the same export 'exportName': RenameCollision.exportName, RenameCollision.finalField, RenameCollision.getSet, RenameCollision.getSet, RenameCollision.method. | |
| int exportName = throw ''; | |
| @JSExport('exportName') | |
| final int finalField = throw ''; | |
| @JSExport('exportName') | |
| int get getSet => throw ''; | |
| @JSExport('exportName') | |
| set getSet(int val) => throw ''; | |
| @JSExport('exportName') | |
| void method() => throw ''; | |
| } | |
| // Allowed collisions are only between getters and setters. | |
| @JSExport() | |
| class GetSetNoCollision { | |
| int get getSet => throw ''; | |
| set getSet(int val) => throw ''; | |
| @JSExport('renamedGetSet') | |
| int get renamedGetter => throw ''; | |
| @JSExport('renamedGetSet') | |
| set renamedSetter(int val) => throw ''; | |
| } | |
| // Class annotation values are warnings | |
| @JSExport('Invalid') | |
| class ClassWithValue { | |
| // ^ | |
| // [web] The value in the `@JSExport` annotation on the class or mixin 'ClassWithValue' will be ignored. | |
| int get getSet => throw ''; | |
| } | |
| @JSExport('Invalid') | |
| mixin MixinWithValue { | |
| // ^ | |
| // [web] The value in the `@JSExport` annotation on the class or mixin 'MixinWithValue' will be ignored. | |
| int get getSet => throw ''; | |
| } | |
| // `JSExport` classes can't export methods that define type parameters as those | |
| // type parameters will never be instantiated through interop. Class type | |
| // parameters are okay, however. | |
| @JSExport() | |
| class GenericAll { | |
| // ^ | |
| // [web] Class 'GenericAll' has no exportable members in the class or the inheritance chain. | |
| void defineTypeParam<T extends int>() {} | |
| T useTypeParam<T extends Object>(T t) => t; | |
| } | |
| class GenericSome<U> { | |
| @JSExport() | |
| void defineTypeParam<T extends int>() {} | |
| // ^ | |
| // [web] Member 'defineTypeParam' is not a concrete instance member or declares type parameters, and therefore can't be exported. | |
| T useTypeParam<T extends Object>(T t) => t; | |
| @JSExport() | |
| U useClassParam(U u) => u; | |
| } | |
| @JSExport() | |
| class ExportUnexportableMembers { | |
| // ^ | |
| // [web] Class 'ExportUnexportableMembers' has no exportable members in the class or the inheritance chain. | |
| @JSExport() | |
| ExportUnexportableMembers(); | |
| // [error column 3] | |
| // [web] Member '<unnamed>' is not a concrete instance member or declares type parameters, and therefore can't be exported. | |
| @JSExport() | |
| factory ExportUnexportableMembers.named() => ExportUnexportableMembers(); | |
| // ^ | |
| // [web] Member 'named' is not a concrete instance member or declares type parameters, and therefore can't be exported. | |
| @JSExport() | |
| static int staticField = 0; | |
| // ^ | |
| // [web] Member 'staticField' is not a concrete instance member or declares type parameters, and therefore can't be exported. | |
| @JSExport() | |
| static int get staticGetSet => 0; | |
| // ^ | |
| // [web] Member 'staticGetSet' is not a concrete instance member or declares type parameters, and therefore can't be exported. | |
| @JSExport() | |
| static set staticGetSet(int _) {} | |
| // ^ | |
| // [web] Member 'staticGetSet' is not a concrete instance member or declares type parameters, and therefore can't be exported. | |
| @JSExport() | |
| static int staticMethod() => 0; | |
| // ^ | |
| // [web] Member 'staticMethod' is not a concrete instance member or declares type parameters, and therefore can't be exported. | |
| } |