1
0
mirror of https://github.com/dart-lang/sdk synced 2024-07-08 12:06:26 +00:00

Revert "[dart:js_interop] Remove Object.toJS and JSNumber.toDart"

This reverts commit 16fcfe7eae.

Reason for revert: Flutter changes haven't landed to google3 yet.

Original change's description:
> [dart:js_interop] Remove Object.toJS and JSNumber.toDart
>
> Modifies JSBoxedDartObject reified type on JS backends and also
> modifies JSBoxedDartObject.toDart now that a proper box is introduced.
> Also uses a JS symbol in JSBoxedDartObject.toDart for a property
> check so that different Dart apps don't accidentally share Dart
> objects. It's now an error to call this function on non-boxed objects.
>
> Fixes a type issue where creating a new object literal with the JS
> foreign function was resulting in dart2js thinking toJSBox would
> always throw. Changing the typeDescription to PlainJavaScriptObject
> instead of =Object fixes that issue.
>
> CoreLibraryReviewExempt: Backend-specific library.
> Change-Id: I5cfb1f32ff4328fafdf9831b0d8da806c39391d9
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/309082
> Reviewed-by: Joshua Litt <joshualitt@google.com>
> Commit-Queue: Srujan Gaddam <srujzs@google.com>

Change-Id: I469ad04db7b49ffef47a46ccac97e909e4865719
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/313580
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Reviewed-by: Joshua Litt <joshualitt@google.com>
Commit-Queue: Srujan Gaddam <srujzs@google.com>
This commit is contained in:
Srujan Gaddam 2023-07-13 21:06:05 +00:00 committed by Commit Queue
parent 16fcfe7eae
commit 2767fca6fe
9 changed files with 50 additions and 44 deletions

View File

@ -1,22 +1,3 @@
## 3.2.0
### Language
### Libraries
#### `dart:js_interop`
- **JSNumber.toDart and Object.toJS**:
`JSNumber.toDart` is removed in favor of `toDartDouble` and `toDartInt` to
make the type explicit. `Object.toJS` is also removed in favor of
`Object.toJSBox`. Previously, this function would allow Dart objects to flow
into JS unwrapped on the JS backends. Now, there's an explicit wrapper that is
added and unwrapped via `JSBoxedDartObject.toDart`. Similarly,
`JSExportedDartObject` is renamed to `JSBoxedDartObject` and the extensions
`ObjectToJSExportedDartObject` and `JSExportedDartObjectToObject` are renamed
to `ObjectToJSBoxedDartObject` and `JSBoxedDartObjectToObject` in order to
avoid confusion with `@JSExport`.
## 3.1.0
### Language

View File

@ -46,8 +46,9 @@ InterfaceType eraseStaticInteropTypesForJSCompilers(
typeArguments = [coreTypes.objectNullableRawType];
break;
case 'JSBoxedDartObject':
erasedClass =
coreTypes.index.getClass('dart:_interceptors', 'JSObject');
// TODO(srujzs): This should be JavaScriptObject once we migrate Flutter
// off of using `Object.toJS`.
erasedClass = coreTypes.objectClass;
break;
case 'JSArrayBuffer':
erasedClass = coreTypes.index.getClass('dart:typed_data', 'ByteBuffer');

View File

@ -72,13 +72,7 @@ extension FunctionToJSExportedDartFunction on Function {
js_util.allowInterop(this) as JSExportedDartFunction;
}
/// Embedded global property for wrapped Dart objects passed via JS interop.
///
/// This is a Symbol so that different Dart applications don't share Dart
/// objects from different Dart runtimes. We expect all [JSBoxedDartObject]s to
/// have this Symbol.
final Object _jsBoxedDartObjectProperty =
foreign_helper.JS('', 'Symbol("jsBoxedDartObjectProperty")');
const _jsBoxedDartObjectProperty = "'_\$jsBoxedDartObject'";
/// [JSBoxedDartObject] <-> [Object]
@patch
@ -86,25 +80,37 @@ extension JSBoxedDartObjectToObject on JSBoxedDartObject {
@patch
@pragma('dart2js:prefer-inline')
Object get toDart {
final val = js_util.getProperty(this, _jsBoxedDartObjectProperty);
if (val == null) {
throw 'Expected a wrapped Dart object, but got a JS object or a wrapped '
'Dart object from a separate runtime instead.';
if (this is JavaScriptObject) {
final val = foreign_helper.JS(
'Object|Null', '#[$_jsBoxedDartObjectProperty]', this);
if (val == null) {
throw 'Expected a wrapped Dart object, but got a JS object instead.';
}
return val as Object;
}
return val as Object;
// TODO(srujzs): Currently we have to still support Dart objects being
// returned from JS until `Object.toJS` is removed. Once that is removed,
// and the runtime type of this type is changed, we can get rid of this and
// the type check above.
return this;
}
}
@patch
extension ObjectToJSBoxedDartObject on Object {
// TODO(srujzs): Remove.
@patch
@pragma('dart2js:prefer-inline')
JSBoxedDartObject get toJS => this as JSBoxedDartObject;
@patch
@pragma('dart2js:prefer-inline')
JSBoxedDartObject get toJSBox {
if (this is JavaScriptObject) {
throw 'Attempting to box non-Dart object.';
}
final box = js_util.newObject();
js_util.setProperty(box, _jsBoxedDartObjectProperty, this);
final box =
foreign_helper.JS('=Object', '{$_jsBoxedDartObjectProperty: #}', this);
return box as JSBoxedDartObject;
}
}
@ -300,6 +306,11 @@ extension ListToJSArray on List<JSAny?> {
/// [JSNumber] -> [double] or [int].
@patch
extension JSNumberToNumber on JSNumber {
// TODO(srujzs): Remove.
@patch
@pragma('dart2js:prefer-inline')
double get toDart => this as double;
@patch
@pragma('dart2js:prefer-inline')
double get toDartDouble => this as double;

View File

@ -67,7 +67,7 @@ dynamic jsify(Object? object) {
Object get globalThis => JS('', 'globalThis');
@patch
T newObject<T>() => JS('PlainJavaScriptObject', '{}');
T newObject<T>() => JS('=Object', '{}');
@patch
bool hasProperty(Object o, Object name) => JS('bool', '# in #', name, o);

View File

@ -110,7 +110,7 @@ class JSArrayIteratorAdapter<T> implements Iterator<T> {
@override
bool moveNext() {
index++;
int length = array.length.toDartInt;
int length = array.length.toDart.toInt();
if (index > length) {
throw 'Iterator out of bounds';
}
@ -132,7 +132,7 @@ class JSArrayIterableAdapter<T> extends EfficientLengthIterable<T> {
Iterator<T> get iterator => JSArrayIteratorAdapter<T>(array);
@override
int get length => array.length.toDartInt;
int get length => array.length.toDart.toInt();
}
// Convert to double to avoid converting to [BigInt] in the case of int64.

View File

@ -88,6 +88,11 @@ extension JSBoxedDartObjectToObject on JSBoxedDartObject {
@patch
extension ObjectToJSBoxedDartObject on Object {
// TODO(srujzs): Remove.
@patch
JSBoxedDartObject get toJS =>
_box<JSBoxedDartObject>(jsObjectFromDartObject(this));
@patch
JSBoxedDartObject get toJSBox {
if (this is JSValue) {
@ -338,6 +343,10 @@ extension ListToJSArray on List<JSAny?> {
/// [JSNumber] -> [double] or [int].
@patch
extension JSNumberToNumber on JSNumber {
// TODO(srujzs): Remove.
@patch
double get toDart => toDartDouble;
@patch
double get toDartDouble => toDartNumber(toExternRef);

View File

@ -176,12 +176,12 @@ class _MatchImplementation implements RegExpMatch {
String get input => _match.input.toDart;
int get start => _match.index.toDartInt;
int get start => _match.index.toDart.toInt();
int get end => (start + (_match[0.toJS].toString()).length);
String? group(int index) {
if (index < 0 || index >= _match.length.toDartInt) {
if (index < 0 || index >= _match.length.toDart.toInt()) {
throw RangeError("Index $index is out of range ${_match.length}");
}
return _match[index.toJS]?.toString();
@ -189,7 +189,7 @@ class _MatchImplementation implements RegExpMatch {
String? operator [](int index) => group(index);
int get groupCount => _match.length.toDartInt - 1;
int get groupCount => _match.length.toDart.toInt() - 1;
List<String?> groups(List<int> groups) {
List<String?> out = [];
@ -311,7 +311,7 @@ int regExpCaptureCount(JSSyntaxRegExp regexp) {
final match = nativeAnchoredRegExp.exec(''.toJS)!;
// The native-anchored regexp always have one capture more than the original,
// and always matches the empty string.
return match.length.toDartInt - 2;
return match.length.toDart.toInt() - 2;
}
/// Find the first match of [regExp] in [string] at or after [start].

View File

@ -197,6 +197,9 @@ extension JSBoxedDartObjectToObject on JSBoxedDartObject {
}
extension ObjectToJSBoxedDartObject on Object {
// TODO(srujzs): Remove. Prefer toJSBox.
external JSBoxedDartObject get toJS;
external JSBoxedDartObject get toJSBox;
}
@ -318,6 +321,9 @@ extension ListToJSArray on List<JSAny?> {
/// [JSNumber] -> [double] or [int].
extension JSNumberToNumber on JSNumber {
// TODO(srujzs): Remove. Prefer toDartDouble or toDartInt.
external double get toDart;
/// Returns a Dart [double] for the given [JSNumber].
external double get toDartDouble;

View File

@ -138,8 +138,6 @@ void syncTests() {
edo = DartObject().toJSBox;
expect(edo is JSBoxedDartObject, true);
expect(((edo as JSBoxedDartObject).toDart as DartObject).foo, 'bar');
// Should not box a non Dart-object.
Expect.throws(() => edo.toJSBox);
// [JSArray] <-> [List<JSAny?>]
arr = [1.0.toJS, 'foo'.toJS].toJS;