mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 00:13:50 +00:00
support @JS annotation from SDK
Attempt at fixing https://github.com/dart-lang/sdk/issues/39740 to allow the flutter web engine to use @JS interop to avoid the overhead of the SDK available js interop. Bug: 39740 Change-Id: I7ba9c8981e639cd267bee3086ba900b89bfc0d6f Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150501 Reviewed-by: Stephen Adams <sra@google.com> Commit-Queue: Harry Terkelsen <het@google.com>
This commit is contained in:
parent
e3fac1dde2
commit
54fe29e965
|
@ -4,18 +4,21 @@
|
|||
|
||||
import 'package:kernel/kernel.dart';
|
||||
|
||||
/// Returns true iff the class has an `@JS(...)` annotation from `package:js`.
|
||||
/// Returns true iff the class has an `@JS(...)` annotation from `package:js`
|
||||
/// or from the internal `dart:_js_annotations`.
|
||||
bool hasJSInteropAnnotation(Class c) =>
|
||||
c.annotations.any(_isPublicJSAnnotation);
|
||||
|
||||
final _packageJs = Uri.parse('package:js/js.dart');
|
||||
final _internalJs = Uri.parse('dart:_js_annotations');
|
||||
|
||||
/// Returns [true] if [e] is the `JS` annotation from `package:js`.
|
||||
bool _isPublicJSAnnotation(Expression value) {
|
||||
var c = _annotationClass(value);
|
||||
return c != null &&
|
||||
c.name == 'JS' &&
|
||||
c.enclosingLibrary.importUri == _packageJs;
|
||||
(c.enclosingLibrary.importUri == _packageJs ||
|
||||
c.enclosingLibrary.importUri == _internalJs);
|
||||
}
|
||||
|
||||
/// Returns the class of the instance referred to by metadata annotation [node].
|
||||
|
|
|
@ -256,6 +256,10 @@ class Uris {
|
|||
/// The URI for 'package:js'.
|
||||
static final Uri package_js = new Uri(scheme: 'package', path: 'js/js.dart');
|
||||
|
||||
/// The URI for 'dart:_js_annotations'.
|
||||
static final Uri dart__js_annotations =
|
||||
Uri(scheme: 'dart', path: '_js_annotations');
|
||||
|
||||
/// The URI for 'package:meta/dart2js.dart'.
|
||||
static final Uri package_meta_dart2js =
|
||||
new Uri(scheme: 'package', path: 'meta/dart2js.dart');
|
||||
|
|
|
@ -111,6 +111,9 @@ abstract class CommonElements {
|
|||
/// The package:js library.
|
||||
LibraryEntity get packageJsLibrary;
|
||||
|
||||
/// The dart:_js_annotations library.
|
||||
LibraryEntity get dartJsAnnotationsLibrary;
|
||||
|
||||
/// The `NativeTypedData` class from dart:typed_data.
|
||||
ClassEntity get typedDataClass;
|
||||
|
||||
|
@ -571,13 +574,35 @@ abstract class CommonElements {
|
|||
ClassEntity cls, NativeBasicData nativeBasicData);
|
||||
|
||||
// From package:js
|
||||
FunctionEntity get jsAllowInterop;
|
||||
FunctionEntity get jsAllowInterop1;
|
||||
|
||||
// From dart:_js_annotations;
|
||||
FunctionEntity get jsAllowInterop2;
|
||||
|
||||
/// Returns `true` if [function] is `allowInterop`.
|
||||
///
|
||||
/// This function can come from either `package:js` or `dart:_js_annotations`.
|
||||
bool isJsAllowInterop(FunctionEntity function);
|
||||
}
|
||||
|
||||
abstract class KCommonElements implements CommonElements {
|
||||
// From package:js
|
||||
ClassEntity get jsAnnotationClass;
|
||||
ClassEntity get jsAnonymousClass;
|
||||
ClassEntity get jsAnnotationClass1;
|
||||
ClassEntity get jsAnonymousClass1;
|
||||
|
||||
// From dart:_js_annotations
|
||||
ClassEntity get jsAnnotationClass2;
|
||||
ClassEntity get jsAnonymousClass2;
|
||||
|
||||
/// Returns `true` if [cls] is a @JS() annotation.
|
||||
///
|
||||
/// The class can come from either `package:js` or `dart:_js_annotations`.
|
||||
bool isJsAnnotationClass(ClassEntity cls);
|
||||
|
||||
/// Returns `true` if [cls] is an @anonymous annotation.
|
||||
///
|
||||
/// The class can come from either `package:js` or `dart:_js_annotations`.
|
||||
bool isJsAnonymousClass(ClassEntity cls);
|
||||
|
||||
ClassEntity get pragmaClass;
|
||||
FieldEntity get pragmaClassNameField;
|
||||
|
@ -824,6 +849,11 @@ class CommonElementsImpl
|
|||
LibraryEntity get packageJsLibrary =>
|
||||
_packageJsLibrary ??= _env.lookupLibrary(Uris.package_js);
|
||||
|
||||
LibraryEntity _dartJsAnnotationsLibrary;
|
||||
@override
|
||||
LibraryEntity get dartJsAnnotationsLibrary => _dartJsAnnotationsLibrary ??=
|
||||
_env.lookupLibrary(Uris.dart__js_annotations);
|
||||
|
||||
ClassEntity _typedDataClass;
|
||||
@override
|
||||
ClassEntity get typedDataClass =>
|
||||
|
@ -1481,22 +1511,57 @@ class CommonElementsImpl
|
|||
_jsConstClass ??= _findClass(foreignLibrary, 'JS_CONST');
|
||||
|
||||
// From dart:js
|
||||
FunctionEntity _jsAllowInterop;
|
||||
FunctionEntity _jsAllowInterop1;
|
||||
@override
|
||||
FunctionEntity get jsAllowInterop => _jsAllowInterop ??=
|
||||
FunctionEntity get jsAllowInterop1 => _jsAllowInterop1 ??=
|
||||
_findLibraryMember(dartJsLibrary, 'allowInterop', required: false);
|
||||
|
||||
// From package:js
|
||||
ClassEntity _jsAnnotationClass;
|
||||
// From dart:_js_annotations
|
||||
FunctionEntity _jsAllowInterop2;
|
||||
@override
|
||||
ClassEntity get jsAnnotationClass => _jsAnnotationClass ??=
|
||||
FunctionEntity get jsAllowInterop2 => _jsAllowInterop2 ??= _findLibraryMember(
|
||||
dartJsAnnotationsLibrary, 'allowInterop',
|
||||
required: false);
|
||||
|
||||
@override
|
||||
bool isJsAllowInterop(FunctionEntity function) {
|
||||
return function == jsAllowInterop1 || function == jsAllowInterop2;
|
||||
}
|
||||
|
||||
// From package:js
|
||||
ClassEntity _jsAnnotationClass1;
|
||||
@override
|
||||
ClassEntity get jsAnnotationClass1 => _jsAnnotationClass1 ??=
|
||||
_findClass(packageJsLibrary, 'JS', required: false);
|
||||
|
||||
ClassEntity _jsAnonymousClass;
|
||||
// From dart:_js_annotations
|
||||
ClassEntity _jsAnnotationClass2;
|
||||
@override
|
||||
ClassEntity get jsAnonymousClass => _jsAnonymousClass ??=
|
||||
ClassEntity get jsAnnotationClass2 => _jsAnnotationClass2 ??=
|
||||
_findClass(dartJsAnnotationsLibrary, 'JS', required: false);
|
||||
|
||||
@override
|
||||
bool isJsAnnotationClass(ClassEntity cls) {
|
||||
return cls == jsAnnotationClass1 || cls == jsAnnotationClass2;
|
||||
}
|
||||
|
||||
// From dart:js
|
||||
ClassEntity _jsAnonymousClass1;
|
||||
@override
|
||||
ClassEntity get jsAnonymousClass1 => _jsAnonymousClass1 ??=
|
||||
_findClass(packageJsLibrary, '_Anonymous', required: false);
|
||||
|
||||
// From dart:_js_annotations
|
||||
ClassEntity _jsAnonymousClass2;
|
||||
@override
|
||||
ClassEntity get jsAnonymousClass2 => _jsAnonymousClass2 ??=
|
||||
_findClass(dartJsAnnotationsLibrary, '_Anonymous', required: false);
|
||||
|
||||
@override
|
||||
bool isJsAnonymousClass(ClassEntity cls) {
|
||||
return cls == jsAnonymousClass1 || cls == jsAnonymousClass2;
|
||||
}
|
||||
|
||||
@override
|
||||
FunctionEntity findHelperFunction(String name) => _findHelperFunction(name);
|
||||
|
||||
|
|
|
@ -295,7 +295,9 @@ String _getReturnsAnnotation(ir.Constant constant) {
|
|||
String _getJsInteropName(ir.Constant constant) {
|
||||
if (constant is ir.InstanceConstant &&
|
||||
constant.classNode.name == 'JS' &&
|
||||
constant.classNode.enclosingLibrary.importUri == Uris.package_js) {
|
||||
(constant.classNode.enclosingLibrary.importUri == Uris.package_js ||
|
||||
constant.classNode.enclosingLibrary.importUri ==
|
||||
Uris.dart__js_annotations)) {
|
||||
assert(constant.fieldValues.length == 1);
|
||||
ir.Constant fieldValue = constant.fieldValues.values.single;
|
||||
if (fieldValue is ir.NullConstant) {
|
||||
|
@ -310,7 +312,9 @@ String _getJsInteropName(ir.Constant constant) {
|
|||
bool _isAnonymousJsInterop(ir.Constant constant) {
|
||||
return constant is ir.InstanceConstant &&
|
||||
constant.classNode.name == '_Anonymous' &&
|
||||
constant.classNode.enclosingLibrary.importUri == Uris.package_js;
|
||||
(constant.classNode.enclosingLibrary.importUri == Uris.package_js ||
|
||||
constant.classNode.enclosingLibrary.importUri ==
|
||||
Uris.dart__js_annotations);
|
||||
}
|
||||
|
||||
class PragmaAnnotationData {
|
||||
|
|
|
@ -562,7 +562,8 @@ class BackendImpacts {
|
|||
|
||||
BackendImpact get allowInterop => _allowInterop ??= BackendImpact(
|
||||
staticUses: [
|
||||
_commonElements.jsAllowInterop,
|
||||
_commonElements.jsAllowInterop1,
|
||||
_commonElements.jsAllowInterop2,
|
||||
],
|
||||
features: EnumSet<BackendFeature>.fromValues([
|
||||
BackendFeature.needToInitializeIsolateAffinityTag,
|
||||
|
|
|
@ -33,8 +33,10 @@ class KernelAnnotationProcessor implements AnnotationProcessor {
|
|||
String annotationName;
|
||||
for (ConstantValue value in metadata) {
|
||||
String name = readAnnotationName(commonElements.dartTypes, spannable,
|
||||
value, commonElements.jsAnnotationClass,
|
||||
defaultValue: '');
|
||||
value, commonElements.jsAnnotationClass1, defaultValue: '') ??
|
||||
readAnnotationName(commonElements.dartTypes, spannable, value,
|
||||
commonElements.jsAnnotationClass2,
|
||||
defaultValue: '');
|
||||
if (annotationName == null) {
|
||||
annotationName = name;
|
||||
} else if (name != null) {
|
||||
|
|
|
@ -2084,7 +2084,8 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
|||
|
||||
List<js.Expression> arguments = visitArguments(node.inputs, start: 0);
|
||||
|
||||
if (element == _commonElements.jsAllowInterop) {
|
||||
if (element == _commonElements.jsAllowInterop1 ||
|
||||
element == _commonElements.jsAllowInterop2) {
|
||||
_nativeData.registerAllowInterop();
|
||||
}
|
||||
|
||||
|
|
218
pkg/compiler/test/jsinterop/internal_annotations_test.dart
Normal file
218
pkg/compiler/test/jsinterop/internal_annotations_test.dart
Normal file
|
@ -0,0 +1,218 @@
|
|||
// Copyright (c) 2016, 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.
|
||||
|
||||
// @dart = 2.7
|
||||
|
||||
library jsinterop.internal_annotations_test;
|
||||
|
||||
import 'package:expect/expect.dart';
|
||||
import 'package:async_helper/async_helper.dart';
|
||||
import 'package:compiler/src/common_elements.dart';
|
||||
import 'package:compiler/src/compiler.dart';
|
||||
import 'package:compiler/src/elements/entities.dart' show ClassEntity;
|
||||
import 'package:compiler/src/elements/names.dart';
|
||||
import 'package:compiler/src/universe/class_hierarchy.dart';
|
||||
import 'package:compiler/src/universe/selector.dart';
|
||||
import 'package:compiler/src/world.dart';
|
||||
import '../helpers/element_lookup.dart';
|
||||
import '../helpers/memory_compiler.dart';
|
||||
|
||||
void main() {
|
||||
asyncTest(() async {
|
||||
await testClasses('package:js/js.dart', 'dart:_js_annotations');
|
||||
await testClasses('package:js/js.dart', 'package:js/js.dart');
|
||||
await testClasses('dart:_js_annotations', 'dart:_js_annotations');
|
||||
});
|
||||
}
|
||||
|
||||
testClasses(String import1, String import2) async {
|
||||
test(String mainSource,
|
||||
{List<String> directlyInstantiated: const <String>[],
|
||||
List<String> abstractlyInstantiated: const <String>[],
|
||||
List<String> indirectlyInstantiated: const <String>[]}) async {
|
||||
String mainFile = 'sdk/tests/dart2js_2/native/main.dart';
|
||||
Uri entryPoint = Uri.parse('memory:$mainFile');
|
||||
CompilationResult result =
|
||||
await runCompiler(entryPoint: entryPoint, memorySourceFiles: {
|
||||
mainFile: """
|
||||
import '$import1' as js1;
|
||||
import '$import2' as js2;
|
||||
|
||||
@js1.JS()
|
||||
class A {
|
||||
external get foo;
|
||||
|
||||
external A(var foo);
|
||||
}
|
||||
|
||||
@js2.JS('BClass')
|
||||
class B {
|
||||
external get foo;
|
||||
|
||||
external B(var foo);
|
||||
}
|
||||
|
||||
@js1.JS()
|
||||
@js1.anonymous
|
||||
class C {
|
||||
external get foo;
|
||||
|
||||
external factory C({foo});
|
||||
}
|
||||
|
||||
@js2.JS()
|
||||
@js2.anonymous
|
||||
class D {
|
||||
external get foo;
|
||||
|
||||
external factory D({foo});
|
||||
}
|
||||
|
||||
class E {
|
||||
final foo;
|
||||
|
||||
E(this.foo);
|
||||
}
|
||||
|
||||
class F {
|
||||
final foo;
|
||||
|
||||
F(this.foo);
|
||||
}
|
||||
|
||||
newA() => new A(0);
|
||||
newB() => new B(1);
|
||||
newC() => new C(foo: 2);
|
||||
newD() => new D(foo: 3);
|
||||
newE() => new E(4);
|
||||
newF() => new F(5);
|
||||
|
||||
$mainSource
|
||||
"""
|
||||
});
|
||||
Compiler compiler = result.compiler;
|
||||
Map<String, ClassEntity> classEnvironment = <String, ClassEntity>{};
|
||||
|
||||
ClassEntity registerClass(ClassEntity cls) {
|
||||
classEnvironment[cls.name] = cls;
|
||||
return cls;
|
||||
}
|
||||
|
||||
JClosedWorld world = compiler.backendClosedWorldForTesting;
|
||||
ElementEnvironment elementEnvironment = world.elementEnvironment;
|
||||
ClassEntity Object_ = registerClass(world.commonElements.objectClass);
|
||||
ClassEntity Interceptor =
|
||||
registerClass(world.commonElements.jsInterceptorClass);
|
||||
ClassEntity JavaScriptObject =
|
||||
registerClass(world.commonElements.jsJavaScriptObjectClass);
|
||||
ClassEntity A = registerClass(findClass(world, 'A'));
|
||||
ClassEntity B = registerClass(findClass(world, 'B'));
|
||||
ClassEntity C = registerClass(findClass(world, 'C'));
|
||||
ClassEntity D = registerClass(findClass(world, 'D'));
|
||||
ClassEntity E = registerClass(findClass(world, 'E'));
|
||||
ClassEntity F = registerClass(findClass(world, 'F'));
|
||||
|
||||
Selector nonExisting = new Selector.getter(const PublicName('nonExisting'));
|
||||
|
||||
Expect.equals(elementEnvironment.getSuperClass(Interceptor), Object_);
|
||||
Expect.equals(
|
||||
elementEnvironment.getSuperClass(JavaScriptObject), Interceptor);
|
||||
|
||||
Expect.equals(elementEnvironment.getSuperClass(A), JavaScriptObject);
|
||||
Expect.equals(elementEnvironment.getSuperClass(B), JavaScriptObject);
|
||||
Expect.equals(elementEnvironment.getSuperClass(C), JavaScriptObject);
|
||||
Expect.equals(elementEnvironment.getSuperClass(D), JavaScriptObject);
|
||||
Expect.equals(elementEnvironment.getSuperClass(E), Object_);
|
||||
Expect.equals(elementEnvironment.getSuperClass(F), Object_);
|
||||
|
||||
Expect.isFalse(world.nativeData.isJsInteropClass(Object_));
|
||||
Expect.isTrue(world.nativeData.isJsInteropClass(A));
|
||||
Expect.isTrue(world.nativeData.isJsInteropClass(B));
|
||||
Expect.isTrue(world.nativeData.isJsInteropClass(C));
|
||||
Expect.isTrue(world.nativeData.isJsInteropClass(D));
|
||||
Expect.isFalse(world.nativeData.isJsInteropClass(E));
|
||||
Expect.isFalse(world.nativeData.isJsInteropClass(F));
|
||||
|
||||
Expect.isFalse(world.nativeData.isAnonymousJsInteropClass(Object_));
|
||||
Expect.isFalse(world.nativeData.isAnonymousJsInteropClass(A));
|
||||
Expect.isFalse(world.nativeData.isAnonymousJsInteropClass(B));
|
||||
Expect.isTrue(world.nativeData.isAnonymousJsInteropClass(C));
|
||||
Expect.isTrue(world.nativeData.isAnonymousJsInteropClass(D));
|
||||
Expect.isFalse(world.nativeData.isAnonymousJsInteropClass(E));
|
||||
Expect.isFalse(world.nativeData.isAnonymousJsInteropClass(F));
|
||||
|
||||
Expect.equals('', world.nativeData.getJsInteropClassName(A));
|
||||
Expect.equals('BClass', world.nativeData.getJsInteropClassName(B));
|
||||
Expect.equals('', world.nativeData.getJsInteropClassName(C));
|
||||
Expect.equals('', world.nativeData.getJsInteropClassName(D));
|
||||
|
||||
for (String name in classEnvironment.keys) {
|
||||
ClassEntity cls = classEnvironment[name];
|
||||
bool isInstantiated = false;
|
||||
if (directlyInstantiated.contains(name)) {
|
||||
isInstantiated = true;
|
||||
Expect.isTrue(
|
||||
world.classHierarchy.isDirectlyInstantiated(cls),
|
||||
"Expected $name to be directly instantiated in `${mainSource}`:"
|
||||
"\n${world.classHierarchy.dump(cls)}");
|
||||
}
|
||||
if (abstractlyInstantiated.contains(name)) {
|
||||
isInstantiated = true;
|
||||
Expect.isTrue(
|
||||
world.classHierarchy.isAbstractlyInstantiated(cls),
|
||||
"Expected $name to be abstractly instantiated in `${mainSource}`:"
|
||||
"\n${world.classHierarchy.dump(cls)}");
|
||||
Expect.isTrue(
|
||||
world.needsNoSuchMethod(cls, nonExisting, ClassQuery.EXACT),
|
||||
"Expected $name to need noSuchMethod for $nonExisting.");
|
||||
Expect.isTrue(
|
||||
world.needsNoSuchMethod(cls, nonExisting, ClassQuery.SUBCLASS),
|
||||
"Expected $name to need noSuchMethod for $nonExisting.");
|
||||
Expect.isTrue(
|
||||
world.needsNoSuchMethod(cls, nonExisting, ClassQuery.SUBTYPE),
|
||||
"Expected $name to need noSuchMethod for $nonExisting.");
|
||||
}
|
||||
if (indirectlyInstantiated.contains(name)) {
|
||||
isInstantiated = true;
|
||||
Expect.isTrue(
|
||||
world.classHierarchy.isIndirectlyInstantiated(cls),
|
||||
"Expected $name to be indirectly instantiated in `${mainSource}`:"
|
||||
"\n${world.classHierarchy.dump(cls)}");
|
||||
}
|
||||
if (!isInstantiated && (name != 'Object' && name != 'Interceptor')) {
|
||||
Expect.isFalse(
|
||||
world.classHierarchy.isInstantiated(cls),
|
||||
"Expected $name to be uninstantiated in `${mainSource}`:"
|
||||
"\n${world.classHierarchy.dump(cls)}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await test('main() {}');
|
||||
|
||||
await test('main() => newA();',
|
||||
abstractlyInstantiated: ['A', 'B', 'C', 'D'],
|
||||
indirectlyInstantiated: ['Object', 'Interceptor', 'JavaScriptObject']);
|
||||
|
||||
await test('main() => newB();',
|
||||
abstractlyInstantiated: ['A', 'B', 'C', 'D'],
|
||||
indirectlyInstantiated: ['Object', 'Interceptor', 'JavaScriptObject']);
|
||||
|
||||
await test('main() => newC();',
|
||||
abstractlyInstantiated: ['A', 'B', 'C', 'D'],
|
||||
indirectlyInstantiated: ['Object', 'Interceptor', 'JavaScriptObject']);
|
||||
|
||||
await test('main() => newD();',
|
||||
abstractlyInstantiated: ['A', 'B', 'C', 'D'],
|
||||
indirectlyInstantiated: ['Object', 'Interceptor', 'JavaScriptObject']);
|
||||
|
||||
await test('main() => newE();', directlyInstantiated: ['E']);
|
||||
|
||||
await test('main() => newF();', directlyInstantiated: ['F']);
|
||||
|
||||
await test('main() => [newD(), newE()];',
|
||||
directlyInstantiated: ['E'],
|
||||
abstractlyInstantiated: ['A', 'B', 'C', 'D'],
|
||||
indirectlyInstantiated: ['Object', 'Interceptor', 'JavaScriptObject']);
|
||||
}
|
|
@ -23,8 +23,12 @@ bool _isLibrary(Library library, List<String> candidates) {
|
|||
|
||||
/// Returns true if [library] represents any library from `package:js` or is the
|
||||
/// internal `dart:_js_helper` library.
|
||||
bool _isJSLibrary(Library library) => _isLibrary(
|
||||
library, ['package:js', 'dart:_js_helper', 'dart:_foreign_helper']);
|
||||
bool _isJSLibrary(Library library) => _isLibrary(library, [
|
||||
'package:js',
|
||||
'dart:_js_helper',
|
||||
'dart:_foreign_helper',
|
||||
'dart:_js_annotations'
|
||||
]);
|
||||
|
||||
/// Whether [node] is a direct call to `allowInterop`.
|
||||
bool isAllowInterop(Expression node) {
|
||||
|
|
|
@ -190,6 +190,8 @@ const Map<String, LibraryInfo> libraries = const {
|
|||
platforms: DART2JS_PLATFORM),
|
||||
"_metadata": const LibraryInfo("html/html_common/metadata.dart",
|
||||
categories: "", documented: false, platforms: DART2JS_PLATFORM),
|
||||
"_js_annotations": const LibraryInfo("js/_js_annotations.dart",
|
||||
categories: "", documented: false, platforms: DART2JS_PLATFORM),
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
19
sdk/lib/js/_js_annotations.dart
Normal file
19
sdk/lib/js/_js_annotations.dart
Normal file
|
@ -0,0 +1,19 @@
|
|||
// Copyright (c) 2015, 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.
|
||||
|
||||
// An implementation of the JS interop classes which are usable from the
|
||||
// Dart SDK. These types need to stay in-sync with
|
||||
// https://github.com/dart-lang/sdk/blob/master/pkg/js/lib/js.dart
|
||||
library _js_annotations;
|
||||
|
||||
class JS {
|
||||
final String name;
|
||||
const JS([this.name]);
|
||||
}
|
||||
|
||||
class _Anonymous {
|
||||
const _Anonymous();
|
||||
}
|
||||
|
||||
const _Anonymous anonymous = const _Anonymous();
|
|
@ -211,6 +211,9 @@
|
|||
"uri": "js/_js.dart",
|
||||
"patches": "js/_js_client.dart"
|
||||
},
|
||||
"_js_annotations": {
|
||||
"uri": "js/_js_annotations.dart"
|
||||
},
|
||||
"js_util": {
|
||||
"uri": "js_util/js_util.dart"
|
||||
},
|
||||
|
@ -321,6 +324,9 @@
|
|||
"uri": "js/_js.dart",
|
||||
"patches": "js/_js_server.dart"
|
||||
},
|
||||
"_js_annotations": {
|
||||
"uri": "js/_js_annotations.dart"
|
||||
},
|
||||
"js_util": {
|
||||
"uri": "js_util/js_util.dart"
|
||||
},
|
||||
|
@ -397,6 +403,9 @@
|
|||
"_isolate_helper": {
|
||||
"uri": "_internal/js_dev_runtime/private/isolate_helper.dart"
|
||||
},
|
||||
"_js_annotations": {
|
||||
"uri": "js/_js_annotations.dart"
|
||||
},
|
||||
"_js_helper": {
|
||||
"uri": "_internal/js_dev_runtime/private/js_helper.dart"
|
||||
},
|
||||
|
|
|
@ -208,6 +208,9 @@ dart2js:
|
|||
uri: "js/_js.dart"
|
||||
patches: "js/_js_client.dart"
|
||||
|
||||
_js_annotations:
|
||||
uri: "js/_js_annotations.dart"
|
||||
|
||||
js_util:
|
||||
uri: "js_util/js_util.dart"
|
||||
|
||||
|
@ -316,6 +319,9 @@ dart2js_server:
|
|||
uri: "js/_js.dart"
|
||||
patches: "js/_js_server.dart"
|
||||
|
||||
_js_annotations:
|
||||
uri: "js/_js_annotations.dart"
|
||||
|
||||
js_util:
|
||||
uri: "js_util/js_util.dart"
|
||||
|
||||
|
@ -390,6 +396,9 @@ dartdevc:
|
|||
_isolate_helper:
|
||||
uri: "_internal/js_dev_runtime/private/isolate_helper.dart"
|
||||
|
||||
_js_annotations:
|
||||
uri: "js/_js_annotations.dart"
|
||||
|
||||
_js_helper:
|
||||
uri: "_internal/js_dev_runtime/private/js_helper.dart"
|
||||
|
||||
|
|
|
@ -190,6 +190,8 @@ const Map<String, LibraryInfo> libraries = const {
|
|||
platforms: DART2JS_PLATFORM),
|
||||
"_metadata": const LibraryInfo("html/html_common/metadata.dart",
|
||||
categories: "", documented: false, platforms: DART2JS_PLATFORM),
|
||||
"_js_annotations": const LibraryInfo("js/_js_annotations.dart",
|
||||
categories: "", documented: false, platforms: DART2JS_PLATFORM),
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
19
sdk_nnbd/lib/js/_js_annotations.dart
Normal file
19
sdk_nnbd/lib/js/_js_annotations.dart
Normal file
|
@ -0,0 +1,19 @@
|
|||
// Copyright (c) 2015, 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.
|
||||
|
||||
// An implementation of the JS interop classes which are usable from the
|
||||
// Dart SDK. These types need to stay in-sync with
|
||||
// https://github.com/dart-lang/sdk/blob/master/pkg/js/lib/js.dart
|
||||
library _js_annotations;
|
||||
|
||||
class JS {
|
||||
final String name;
|
||||
const JS([this.name]);
|
||||
}
|
||||
|
||||
class _Anonymous {
|
||||
const _Anonymous();
|
||||
}
|
||||
|
||||
const _Anonymous anonymous = const _Anonymous();
|
|
@ -211,6 +211,9 @@
|
|||
"uri": "js/_js.dart",
|
||||
"patches": "js/_js_client.dart"
|
||||
},
|
||||
"_js_annotations": {
|
||||
"uri": "js/_js_annotations.dart"
|
||||
},
|
||||
"js_util": {
|
||||
"uri": "js_util/js_util.dart"
|
||||
},
|
||||
|
@ -321,6 +324,9 @@
|
|||
"uri": "js/_js.dart",
|
||||
"patches": "js/_js_server.dart"
|
||||
},
|
||||
"_js_annotations": {
|
||||
"uri": "js/_js_annotations.dart"
|
||||
},
|
||||
"js_util": {
|
||||
"uri": "js_util/js_util.dart"
|
||||
},
|
||||
|
@ -397,6 +403,9 @@
|
|||
"_isolate_helper": {
|
||||
"uri": "_internal/js_dev_runtime/private/isolate_helper.dart"
|
||||
},
|
||||
"_js_annotations": {
|
||||
"uri": "js/_js_annotations.dart"
|
||||
},
|
||||
"_js_helper": {
|
||||
"uri": "_internal/js_dev_runtime/private/js_helper.dart"
|
||||
},
|
||||
|
|
|
@ -208,6 +208,9 @@ dart2js:
|
|||
uri: "js/_js.dart"
|
||||
patches: "js/_js_client.dart"
|
||||
|
||||
_js_annotations:
|
||||
uri: "js/_js_annotations.dart"
|
||||
|
||||
js_util:
|
||||
uri: "js_util/js_util.dart"
|
||||
|
||||
|
@ -316,6 +319,9 @@ dart2js_server:
|
|||
uri: "js/_js.dart"
|
||||
patches: "js/_js_server.dart"
|
||||
|
||||
_js_annotations:
|
||||
uri: "js/_js_annotations.dart"
|
||||
|
||||
js_util:
|
||||
uri: "js_util/js_util.dart"
|
||||
|
||||
|
@ -390,6 +396,9 @@ dartdevc:
|
|||
_isolate_helper:
|
||||
uri: "_internal/js_dev_runtime/private/isolate_helper.dart"
|
||||
|
||||
_js_annotations:
|
||||
uri: "js/_js_annotations.dart"
|
||||
|
||||
_js_helper:
|
||||
uri: "_internal/js_dev_runtime/private/js_helper.dart"
|
||||
|
||||
|
|
Loading…
Reference in a new issue