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

[dart:js_interop] Relabel globalJSObject as globalContext and point to object used in static interop lowerings

This is likely more useful than returning globalThis always. It
allows users to workaround issues with lowerings without having
to worry about browser compatibility differences.

CoreLibraryReviewExempt: Backend-specific library.
Change-Id: I01479211fe6b573c845de5b134d36338c40fc10d
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/319301
Reviewed-by: Sigmund Cherem <sigmund@google.com>
Commit-Queue: Srujan Gaddam <srujzs@google.com>
This commit is contained in:
Srujan Gaddam 2023-08-15 20:57:17 +00:00 committed by Commit Queue
parent 66b511fa6c
commit ad62f6033b
6 changed files with 53 additions and 50 deletions

View File

@ -57,7 +57,9 @@
case in Dart2JS and DDC. We used either `self` or DDC's `global` in non-static
interop APIs with `package:js`. So, static interop APIs will now use one of
those global contexts. Functionally, this should matter in only a very small
number of cases, like when using older browser versions.
number of cases, like when using older browser versions. `dart:js_interop`'s
`globalJSObject` is also renamed to `globalContext` and returns the global
context used in the lowerings.
## 3.1.0

View File

@ -27,7 +27,7 @@ class ExportCreator extends Transformer {
final ExportChecker _exportChecker;
final Procedure _functionToJS;
final Procedure _getProperty;
final Procedure _globalJSObject;
final Procedure _globalContext;
final Class _jsAny;
final Class _jsObject;
final Procedure _setProperty;
@ -48,8 +48,8 @@ class ExportCreator extends Transformer {
'dart:js_interop', 'FunctionToJSExportedDartFunction|get#toJS'),
_getProperty = _typeEnvironment.coreTypes.index.getTopLevelProcedure(
'dart:js_interop_unsafe', 'JSObjectUtilExtension|[]'),
_globalJSObject = _typeEnvironment.coreTypes.index
.getTopLevelProcedure('dart:js_interop', 'get:globalJSObject'),
_globalContext = _typeEnvironment.coreTypes.index
.getTopLevelProcedure('dart:js_interop', 'get:globalContext'),
_jsAny = _typeEnvironment.coreTypes.index
.getClass('dart:_js_types', 'JSAny'),
_jsObject = _typeEnvironment.coreTypes.index
@ -201,7 +201,7 @@ class ExportCreator extends Transformer {
// Get the global 'Object' property.
Expression getObjectProperty() => asJSObject(StaticInvocation(_getProperty,
Arguments([StaticGet(_globalJSObject), toJSString('Object')])))
Arguments([StaticGet(_globalContext), toJSString('Object')])))
..fileOffset = node.fileOffset;
// Get a fresh object literal, using the proto to create it if one was

View File

@ -5,13 +5,14 @@
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_types';
import 'dart:js_util' as js_util;
import 'dart:typed_data';
@patch
@pragma('dart2js:prefer-inline')
JSObject get globalJSObject => js_util.globalThis as JSObject;
JSObject get globalContext => staticInteropGlobalContext as JSObject;
/// Helper for working with the [JSAny?] top type in a backend agnostic way.
/// TODO(joshualitt): Remove conflation of null and undefined after migration.

View File

@ -17,10 +17,9 @@ 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;
// TODO(joshualitt): Eventually delete `dart:js_util` on Dart2Wasm and migrate
// any used logic to this file.
// This should match the global context we use in our static interop lowerings.
@patch
JSObject get globalJSObject => js_util.globalThis as JSObject;
JSObject get globalContext => js_util.globalThis as JSObject;
/// Helper for working with the [JSAny?] top type in a backend agnostic way.
@patch

View File

@ -136,8 +136,9 @@ typedef JSBoolean = js_types.JSBoolean;
/// The type of JS strings, [JSString] <: [JSAny].
typedef JSString = js_types.JSString;
/// A getter to retrieve the Global [JSObject].
external JSObject get globalJSObject;
/// A getter to retrieve the global context that is used in static interop
/// lowering.
external JSObject get globalContext;
/// `JSUndefined` and `JSNull` are actual reified types on some backends, but
/// not others. Instead, users should use nullable types for any type that could

View File

@ -44,11 +44,11 @@ void equalTest() {
globalThis.funcData = function JSClass() {}
globalThis.JSClass = new globalThis.funcData();
''');
JSObject gt = globalJSObject;
JSObject gc = globalContext;
void test(String propertyName, bool testCanonicalization) {
Expect.equals(gt[propertyName.toJS], gt[propertyName.toJS]);
Expect.equals(gc[propertyName.toJS], gc[propertyName.toJS]);
if (testCanonicalization) {
Expect.equals(gt[propertyName.toJS], gt[(propertyName + "2").toJS]);
Expect.equals(gc[propertyName.toJS], gc[(propertyName + "2").toJS]);
}
}
@ -83,11 +83,11 @@ void typeofTest() {
};
void test(String property, String expectedType) {
Expect.isTrue(
globalJSObject[property.toJS]?.typeofEquals(expectedType.toJS).toDart);
globalContext[property.toJS]?.typeofEquals(expectedType.toJS).toDart);
for (final type in types) {
if (type != expectedType) {
Expect.isFalse(
globalJSObject[property.toJS]?.typeofEquals(type.toJS).toDart);
globalContext[property.toJS]?.typeofEquals(type.toJS).toDart);
}
}
}
@ -109,10 +109,10 @@ void instanceOfTest() {
globalThis.obj = new JSClass1();
''');
JSObject gt = globalJSObject;
JSObject obj = gt['obj'.toJS] as JSObject;
JSFunction jsClass1Constructor = gt['JSClass1'.toJS] as JSFunction;
JSFunction jsClass2Constructor = gt['JSClass2'.toJS] as JSFunction;
JSObject gc = globalContext;
JSObject obj = gc['obj'.toJS] as JSObject;
JSFunction jsClass1Constructor = gc['JSClass1'.toJS] as JSFunction;
JSFunction jsClass2Constructor = gc['JSClass2'.toJS] as JSFunction;
Expect.isTrue(obj.instanceof(jsClass1Constructor).toDart);
Expect.isFalse(obj.instanceof(jsClass2Constructor).toDart);
}
@ -151,8 +151,8 @@ void evalAndConstructTest() {
}
globalThis.JSClass = JSClass;
''');
JSObject gt = globalJSObject;
JSFunction constructor = gt['JSClass'.toJS] as JSFunction;
JSObject gc = globalContext;
JSFunction constructor = gc['JSClass'.toJS] as JSFunction;
// Var args
JSObject jsObj1 =
@ -267,17 +267,17 @@ void deepConversionsTest() {
globalThis.keyObject1 = keyObject;
globalThis.keyObject2 = keyObject;
''');
JSObject gt = globalJSObject;
Expect.isNull(gt['a'.toJS]);
Expect.equals('foo', gt.getProperty<JSString>('b'.toJS).toDart);
JSObject gc = globalContext;
Expect.isNull(gc['a'.toJS]);
Expect.equals('foo', gc.getProperty<JSString>('b'.toJS).toDart);
_expectRecEquals(
['a', 'b', 'c'],
gt
gc
.getProperty<JSArray>('c'.toJS)
.toDart
.map((JSAny? o) => (o as JSString).toDart));
Expect.equals(2.5, gt.getProperty<JSNumber>('d'.toJS).toDartDouble);
Expect.equals(true, gt.getProperty<JSBoolean>('e'.toJS).toDart);
Expect.equals(2.5, gc.getProperty<JSNumber>('d'.toJS).toDartDouble);
Expect.equals(true, gc.getProperty<JSBoolean>('e'.toJS).toDart);
_expectRecEquals({
'null': 'foo',
'foo': null,
@ -289,40 +289,40 @@ void deepConversionsTest() {
'f': 2,
'g': [2, 4, 6]
},
}, gt.getProperty('g'.toJS).dartify());
}, gc.getProperty('g'.toJS).dartify());
_expectRecEquals({
'a': {},
}, gt.getProperty('rec'.toJS).dartify());
}, gc.getProperty('rec'.toJS).dartify());
_expectIterableEquals(Int8List.fromList(<int>[-128, 0, 127]),
gt.getProperty<JSInt8Array>('int8Array'.toJS).toDart);
gc.getProperty<JSInt8Array>('int8Array'.toJS).toDart);
_expectIterableEquals(Uint8List.fromList([-1, 0, 255, 256]),
gt.getProperty<JSUint8Array>('uint8Array'.toJS).toDart);
gc.getProperty<JSUint8Array>('uint8Array'.toJS).toDart);
_expectIterableEquals(Uint8ClampedList.fromList([-1, 0, 255, 256]),
gt.getProperty<JSUint8ClampedArray>('uint8ClampedArray'.toJS).toDart);
gc.getProperty<JSUint8ClampedArray>('uint8ClampedArray'.toJS).toDart);
_expectIterableEquals(Int16List.fromList([-32769, -32768, 0, 32767, 32768]),
gt.getProperty<JSInt16Array>('int16Array'.toJS).toDart);
gc.getProperty<JSInt16Array>('int16Array'.toJS).toDart);
_expectIterableEquals(Uint16List.fromList([-1, 0, 65535, 65536]),
gt.getProperty<JSUint16Array>('uint16Array'.toJS).toDart);
gc.getProperty<JSUint16Array>('uint16Array'.toJS).toDart);
_expectIterableEquals(Int32List.fromList([-2147483648, 0, 2147483647]),
gt.getProperty<JSInt32Array>('int32Array'.toJS).toDart);
gc.getProperty<JSInt32Array>('int32Array'.toJS).toDart);
_expectIterableEquals(Uint32List.fromList([-1, 0, 4294967295, 4294967296]),
gt.getProperty<JSUint32Array>('uint32Array'.toJS).toDart);
gc.getProperty<JSUint32Array>('uint32Array'.toJS).toDart);
_expectIterableEquals(
Float32List.fromList([-1000.488, -0.00001, 0.0001, 10004.888]),
gt.getProperty<JSFloat32Array>('float32Array'.toJS).toDart);
gc.getProperty<JSFloat32Array>('float32Array'.toJS).toDart);
_expectIterableEquals(
Float64List.fromList([-1000.488, -0.00001, 0.0001, 10004.888]),
gt.getProperty<JSFloat64Array>('float64Array'.toJS).toDart);
gc.getProperty<JSFloat64Array>('float64Array'.toJS).toDart);
_expectIterableEquals(Uint8List.fromList([-1, 0, 255, 256]),
gt.getProperty<JSArrayBuffer>('arrayBuffer'.toJS).toDart.asUint8List());
gc.getProperty<JSArrayBuffer>('arrayBuffer'.toJS).toDart.asUint8List());
_expectIterableEquals(Uint8List.fromList([-1, 0, 255, 256]),
gt.getProperty<JSDataView>('dataView'.toJS).toDart.buffer.asUint8List());
gc.getProperty<JSDataView>('dataView'.toJS).toDart.buffer.asUint8List());
// Confirm a function that takes a roundtrip remains a function.
JSFunction foo = gt['f'.toJS].dartify() as JSFunction;
JSFunction foo = gc['f'.toJS].dartify() as JSFunction;
Expect.equals(
'hello world', gt.callMethod<JSString>('invoke'.toJS, foo).toDart);
'hello world', gc.callMethod<JSString>('invoke'.toJS, foo).toDart);
// Confirm arrays, which need to be converted implicitly, are still
// recursively converted by dartify() when desired.
@ -334,12 +334,12 @@ void deepConversionsTest() {
3,
{'baz': 'boo'}
],
], gt['implicitExplicit'.toJS].dartify() as Iterable);
], gc['implicitExplicit'.toJS].dartify() as Iterable);
// Test that JS objects behave as expected in Map / Set.
Set<Object?> set = {};
JSAny? key1 = gt['keyObject1'.toJS];
JSAny? key2 = gt['keyObject2'.toJS];
JSAny? key1 = gc['keyObject1'.toJS];
JSAny? key2 = gc['keyObject2'.toJS];
Expect.isTrue(set.add(key1));
Expect.isTrue(set.contains(key1));
Expect.isFalse(set.add(key2));
@ -384,17 +384,17 @@ void symbolTest() {
}
globalThis.symbol2 = symbol2;
''');
JSObject gt = globalJSObject;
JSObject gc = globalContext;
Expect.equals(
_JSSymbol.keyFor(_JSSymbol._for('symbol'.toJS)).toDart, 'symbol');
Expect.equals(
gt.getProperty<JSString>(gt.getProperty<JSAny>('symbol'.toJS)).toDart,
gc.getProperty<JSString>(gc.getProperty<JSAny>('symbol'.toJS)).toDart,
'boo');
Expect.equals(methodWithSymbol(symbol).toDart, 'symbol');
Expect.equals(_JSSymbol.keyFor(symbol).toDart, 'symbol');
Expect.equals(
_JSSymbol.keyFor(gt.getProperty<JSAny>('symbol'.toJS)).toDart, 'symbol');
Expect.equals(gt.callMethod<JSString>(symbol2).toDart, 'hello world');
_JSSymbol.keyFor(gc.getProperty<JSAny>('symbol'.toJS)).toDart, 'symbol');
Expect.equals(gc.callMethod<JSString>(symbol2).toDart, 'hello world');
}
void main() {