[dart:js_interop] Add JS types for Symbol/BigInt
Adds JSSymbol and JSBigInt and erases to either their respective interceptor types in the JS backends or JSValue in dart2wasm. CoreLibraryReviewExempt: Backend-specific library. Change-Id: Ib2c70d22a70c6308733cd170b91eafa8ec3b3aeb Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/321749 Reviewed-by: Sigmund Cherem <sigmund@google.com>
This commit is contained in:
committed by
Commit Queue
parent
c738fe1d7b
commit
a38fb595cf
+6
-2
@@ -90,7 +90,9 @@
|
||||
interceptor and should not be used with `package:js` classes. These types were
|
||||
being intercepted with the assumption that they are a subtype of JavaScript's
|
||||
`Object`, but this is incorrect. This lead to erroneous behavior when using
|
||||
these types as Dart `Object`s. See [#53106][] for more details.
|
||||
these types as Dart `Object`s. See [#53106][] for more details. Use
|
||||
`dart:js_interop`'s `JSSymbol` and `JSBigInt` with extension types to interop
|
||||
with these types.
|
||||
|
||||
#### Dart2js
|
||||
|
||||
@@ -99,7 +101,9 @@
|
||||
interceptor and should not be used with `package:js` classes. These types were
|
||||
being intercepted with the assumption that they are a subtype of JavaScript's
|
||||
`Object`, but this is incorrect. This lead to erroneous behavior when using
|
||||
these types as Dart `Object`s. See [#53106][] for more details.
|
||||
these types as Dart `Object`s. See [#53106][] for more details. Use
|
||||
`dart:js_interop`'s `JSSymbol` and `JSBigInt` with extension types to interop
|
||||
with these types.
|
||||
|
||||
[#53106]: https://github.com/dart-lang/sdk/issues/53106
|
||||
|
||||
|
||||
@@ -101,6 +101,14 @@ InterfaceType eraseStaticInteropTypesForJSCompilers(
|
||||
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';
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ class JsInteropClass {
|
||||
native:JSAny,
|
||||
native:JSArray,
|
||||
native:JSArrayBuffer,
|
||||
native:JSBigInt,
|
||||
native:JSBoolean,
|
||||
native:JSBoxedDartObject,
|
||||
native:JSDataView,
|
||||
@@ -49,6 +50,7 @@ class JsInteropClass {
|
||||
native:JSObject,
|
||||
native:JSPromise,
|
||||
native:JSString,
|
||||
native:JSSymbol,
|
||||
native:JSTypedArray,
|
||||
native:JSUint16Array,
|
||||
native:JSUint32Array,
|
||||
|
||||
@@ -58,6 +58,7 @@ import 'package:js/js.dart';
|
||||
native:JSAny,
|
||||
native:JSArray,
|
||||
native:JSArrayBuffer,
|
||||
native:JSBigInt,
|
||||
native:JSBoolean,
|
||||
native:JSBoxedDartObject,
|
||||
native:JSDataView,
|
||||
@@ -72,6 +73,7 @@ import 'package:js/js.dart';
|
||||
native:JSObject,
|
||||
native:JSPromise,
|
||||
native:JSString,
|
||||
native:JSSymbol,
|
||||
native:JSTypedArray,
|
||||
native:JSUint16Array,
|
||||
native:JSUint32Array,
|
||||
|
||||
@@ -65,6 +65,7 @@ import 'package:js/js.dart';
|
||||
native:JSAny,
|
||||
native:JSArray,
|
||||
native:JSArrayBuffer,
|
||||
native:JSBigInt,
|
||||
native:JSBoolean,
|
||||
native:JSBoxedDartObject,
|
||||
native:JSDataView,
|
||||
@@ -79,6 +80,7 @@ import 'package:js/js.dart';
|
||||
native:JSObject,
|
||||
native:JSPromise,
|
||||
native:JSString,
|
||||
native:JSSymbol,
|
||||
native:JSTypedArray,
|
||||
native:JSUint16Array,
|
||||
native:JSUint32Array,
|
||||
|
||||
@@ -51,6 +51,7 @@ class JSExportedDartFunction implements JSFunction {}
|
||||
@staticInterop
|
||||
class JSArray implements JSObject {
|
||||
external factory JSArray();
|
||||
// TODO(srujzs): Should we make this an `int`?
|
||||
external factory JSArray.withLength(JSNumber length);
|
||||
}
|
||||
|
||||
@@ -118,6 +119,14 @@ class JSBoolean implements JSAny {}
|
||||
@staticInterop
|
||||
class JSString implements JSAny {}
|
||||
|
||||
@JS()
|
||||
@staticInterop
|
||||
class JSSymbol implements JSAny {}
|
||||
|
||||
@JS()
|
||||
@staticInterop
|
||||
class JSBigInt implements JSAny {}
|
||||
|
||||
/// [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.
|
||||
|
||||
@@ -99,6 +99,7 @@ class JSPromise implements JSObject {}
|
||||
@staticInterop
|
||||
class JSArray implements JSObject {
|
||||
external factory JSArray();
|
||||
// TODO(srujzs): Should we make this an `int`?
|
||||
external factory JSArray.withLength(JSNumber length);
|
||||
}
|
||||
|
||||
@@ -166,6 +167,14 @@ class JSBoolean implements JSAny {}
|
||||
@staticInterop
|
||||
class JSString implements JSAny {}
|
||||
|
||||
@JS()
|
||||
@staticInterop
|
||||
class JSSymbol implements JSAny {}
|
||||
|
||||
@JS()
|
||||
@staticInterop
|
||||
class JSBigInt implements JSAny {}
|
||||
|
||||
/// [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.
|
||||
|
||||
@@ -136,6 +136,12 @@ typedef JSBoolean = js_types.JSBoolean;
|
||||
/// The type of JS strings, [JSString] <: [JSAny].
|
||||
typedef JSString = js_types.JSString;
|
||||
|
||||
/// The type of JS Symbols, [JSSymbol] <: [JSAny].
|
||||
typedef JSSymbol = js_types.JSSymbol;
|
||||
|
||||
/// The type of JS BigInts, [JSBigInt] <: [JSAny].
|
||||
typedef JSBigInt = js_types.JSBigInt;
|
||||
|
||||
/// A getter to retrieve the global context that is used in static interop
|
||||
/// lowering.
|
||||
external JSObject get globalContext;
|
||||
|
||||
@@ -88,6 +88,28 @@ external JSBoolean boo;
|
||||
@JS()
|
||||
external JSString str;
|
||||
|
||||
@JS()
|
||||
external JSSymbol symbol;
|
||||
|
||||
@JS('Symbol')
|
||||
external JSSymbol createSymbol(String value);
|
||||
|
||||
extension on JSSymbol {
|
||||
@JS('toString')
|
||||
external String toStringExternal();
|
||||
}
|
||||
|
||||
@JS()
|
||||
external JSBigInt bigInt;
|
||||
|
||||
@JS('BigInt')
|
||||
external JSBigInt createBigInt(String value);
|
||||
|
||||
extension on JSBigInt {
|
||||
@JS('toString')
|
||||
external String toStringExternal();
|
||||
}
|
||||
|
||||
@JS()
|
||||
external JSAny? nullAny;
|
||||
|
||||
@@ -240,6 +262,16 @@ void syncTests() {
|
||||
String dartStr = str.toDart;
|
||||
expect(dartStr, 'foo');
|
||||
|
||||
// [JSSymbol]
|
||||
symbol = createSymbol('foo');
|
||||
expect(symbol is JSSymbol, true);
|
||||
expect(symbol.toStringExternal(), 'Symbol(foo)');
|
||||
|
||||
// [JSBigInt]
|
||||
bigInt = createBigInt('9876543210000000000000123456789');
|
||||
expect(bigInt is JSBigInt, true);
|
||||
expect(bigInt.toStringExternal(), '9876543210000000000000123456789');
|
||||
|
||||
// null and undefined can flow into `JSAny?`.
|
||||
// TODO(joshualitt): Fix tests when `JSNull` and `JSUndefined` are no longer
|
||||
// conflated.
|
||||
|
||||
Reference in New Issue
Block a user