[dart2wasm] Wire up stubbed out dart:js on dart2wasm

Change-Id: Ia06db4b1b2f3d07278819936842a4185cc9a45f8
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/247329
Reviewed-by: Srujan Gaddam <srujzs@google.com>
Commit-Queue: Joshua Litt <joshualitt@google.com>
This commit is contained in:
Joshua Litt 2022-06-08 20:38:52 +00:00 committed by Commit Bot
parent 3e17635bca
commit 3fd96e2cb8
12 changed files with 170 additions and 59 deletions

View file

@ -60,12 +60,10 @@ List<String> getNativeNames(Annotatable a) {
}
final _packageJs = Uri.parse('package:js/js.dart');
final _jsWasm = Uri.parse('dart:js_wasm');
final _internalJs = Uri.parse('dart:_js_annotations');
final _jsHelper = Uri.parse('dart:_js_helper');
bool _isAnyInteropUri(Uri uri) =>
uri == _packageJs || uri == _internalJs || uri == _jsWasm;
bool _isAnyInteropUri(Uri uri) => uri == _packageJs || uri == _internalJs;
/// Returns true if [value] is the interop annotation whose class is
/// [annotationClassName] from `package:js` or from `dart:_js_annotations`.

View file

@ -78,11 +78,11 @@ class JsUtilWasmOptimizer extends Transformer {
_jsifyRawTarget = _coreTypes.index
.getTopLevelProcedure('dart:_js_helper', 'jsifyRaw'),
_wrapDartCallbackTarget = _coreTypes.index
.getTopLevelProcedure('dart:js_util_wasm', '_wrapDartCallback'),
.getTopLevelProcedure('dart:_js_helper', '_wrapDartCallback'),
_newObjectTarget =
_coreTypes.index.getTopLevelProcedure('dart:js_util', 'newObject'),
_allowInteropTarget = _coreTypes.index
.getTopLevelProcedure('dart:js_util_wasm', 'allowInterop'),
_allowInteropTarget =
_coreTypes.index.getTopLevelProcedure('dart:js', 'allowInterop'),
_wasmAnyRefClass = _coreTypes.index.getClass('dart:wasm', 'WasmAnyRef'),
_objectClass = _coreTypes.objectClass,
_pragmaClass = _coreTypes.pragmaClass,
@ -283,8 +283,10 @@ class JsUtilWasmOptimizer extends Transformer {
StaticInvocation _allowInterop(
Procedure node, FunctionType type, Expression argument) {
String callbackTrampolineName = _createCallbackTrampoline(node, type);
return StaticInvocation(_wrapDartCallbackTarget,
Arguments([argument, StringLiteral(callbackTrampolineName)]));
return StaticInvocation(
_wrapDartCallbackTarget,
Arguments([argument, StringLiteral(callbackTrampolineName)],
types: [type]));
}
StaticGet get _globalThis => StaticGet(_globalThisMember);

View file

@ -50,9 +50,8 @@ class WasmTarget extends Target {
'dart:_js_helper',
'dart:typed_data',
'dart:nativewrappers',
'dart:js',
'dart:js_util',
'dart:js_util_wasm',
'dart:js_wasm',
'dart:wasm',
'dart:developer',
];
@ -62,9 +61,8 @@ class WasmTarget extends Target {
'dart:_js_helper',
'dart:collection',
'dart:typed_data',
'dart:js',
'dart:js_util',
'dart:js_util_wasm',
'dart:js_wasm',
'dart:wasm',
];
@ -107,7 +105,7 @@ class WasmTarget extends Target {
ChangedStructureNotifier? changedStructureNotifier}) {
List<Library>? transitiveImportingJSInterop =
jsInteropHelper.calculateTransitiveImportsOfJsInteropIfUsed(
component, Uri.parse("dart:js_wasm"));
component, Uri.parse("package:js/js.dart"));
if (transitiveImportingJSInterop == null) {
logger?.call("Skipped JS interop transformations");
} else {

View file

@ -87,9 +87,21 @@ external WasmAnyRef? setPropertyRaw(
external WasmAnyRef? callMethodVarArgsRaw(
WasmAnyRef o, WasmAnyRef method, WasmAnyRef? args);
// Currently, `allowInterop` returns a Function type. This is unfortunate for
// Dart2wasm because it means arbitrary Dart functions can flow to JS util
// calls. Our only solutions is to cache every function called with
// `allowInterop` and to replace them with the wrapped variant when they flow
// to JS.
// NOTE: We are not currently replacing functions returned from JS.
Map<Function, JSValue> functionToJSWrapper = {};
WasmAnyRef? jsifyRaw(Object? object) {
if (object == null) {
return null;
} else if (object is Function) {
assert(functionToJSWrapper.containsKey(object),
'Must call `allowInterop` on functions before they flow to JS');
return functionToJSWrapper[object]?.toAnyRef();
} else if (object is JSValue) {
return object.toAnyRef();
} else if (object is String) {
@ -101,7 +113,21 @@ WasmAnyRef? jsifyRaw(Object? object) {
}
}
/// js_util_wasm methods used by the wasm runtime.
@pragma("wasm:import", "dart2wasm.wrapDartCallback")
external WasmAnyRef _wrapDartCallbackRaw(
WasmAnyRef callback, WasmAnyRef trampolineName);
F _wrapDartCallback<F extends Function>(F f, String trampolineName) {
if (functionToJSWrapper.containsKey(f)) {
return f;
}
JSValue wrappedFunction = JSValue(_wrapDartCallbackRaw(
f.toJS().toAnyRef(), trampolineName.toJS().toAnyRef()));
functionToJSWrapper[f] = wrappedFunction;
return f;
}
/// Methods used by the wasm runtime.
@pragma("wasm:export", "\$listLength")
double _listLength(List list) => list.length.toDouble();

View file

@ -0,0 +1,120 @@
// Copyright (c) 2022, 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.
// This library is only supported on dart2wasm because of [allowInterop].
library dart.js;
import 'dart:_internal' show patch;
import 'dart:_js_helper';
import 'dart:collection' show ListMixin;
import 'dart:wasm';
@patch
JsObject get context => throw UnimplementedError;
@patch
class JsObject {
// No argument empty constructor to support inheritance.
JsObject._() {
throw UnimplementedError;
}
@patch
factory JsObject(JsFunction constructor, [List? arguments]) =>
throw UnimplementedError;
@patch
factory JsObject.fromBrowserObject(Object object) => throw UnimplementedError;
@patch
factory JsObject.jsify(Object object) => throw UnimplementedError;
@patch
dynamic operator [](Object property) => throw UnimplementedError;
@patch
void operator []=(Object property, Object? value) => throw UnimplementedError;
@patch
bool operator ==(Object other) => throw UnimplementedError;
@patch
bool hasProperty(Object property) => throw UnimplementedError;
@patch
void deleteProperty(Object property) => throw UnimplementedError;
@patch
bool instanceof(JsFunction type) => throw UnimplementedError;
@patch
String toString() => throw UnimplementedError;
@patch
dynamic callMethod(Object method, [List? args]) => throw UnimplementedError;
}
@patch
class JsFunction extends JsObject {
@patch
factory JsFunction.withThis(Function f) => throw UnimplementedError;
@patch
dynamic apply(List args, {thisArg}) => throw UnimplementedError;
}
@patch
class JsArray<E> extends JsObject with ListMixin<E> {
@patch
factory JsArray() => throw UnimplementedError;
@patch
factory JsArray.from(Iterable<E> other) => throw UnimplementedError;
@patch
E operator [](Object index) => throw UnimplementedError;
@patch
void operator []=(Object index, E value) => throw UnimplementedError;
@patch
int get length => throw UnimplementedError;
@patch
void set length(int length) => throw UnimplementedError;
@patch
void add(E value) => throw UnimplementedError;
@patch
void addAll(Iterable<E> iterable) => throw UnimplementedError;
@patch
void insert(int index, E element) => throw UnimplementedError;
@patch
E removeAt(int index) => throw UnimplementedError;
@patch
E removeLast() => throw UnimplementedError;
@patch
void removeRange(int start, int end) => throw UnimplementedError;
@patch
void setRange(int start, int end, Iterable<E> iterable,
[int skipCount = 0]) =>
throw UnimplementedError;
@patch
void sort([int compare(E a, E b)?]) => throw UnimplementedError;
}
/// This will be lowered to a a call to `_wrapDartCallback`.
@patch
F allowInterop<F extends Function>(F f) => throw UnimplementedError;
@patch
Function allowInteropCaptureThis(Function f) => throw UnimplementedError;

View file

@ -1,21 +0,0 @@
// Copyright (c) 2022, 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.
library dart.js_util_wasm;
import "dart:_internal";
import "dart:_js_helper";
import "dart:wasm";
@patch
Object allowInterop<F extends Function>(F f) => throw 'unreachable';
@pragma("wasm:import", "dart2wasm.wrapDartCallback")
external WasmAnyRef _wrapDartCallbackRaw(
WasmAnyRef callback, WasmAnyRef trampolineName);
JSValue? _wrapDartCallback(Object callback, String trampolineName) {
return JSValue(_wrapDartCallbackRaw(
callback.toJS().toAnyRef(), trampolineName.toJS().toAnyRef()));
}

View file

@ -2,7 +2,4 @@
# 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.
js_util_sdk_sources = [
"js_util.dart",
"js_util_wasm.dart",
]
js_util_sdk_sources = [ "js_util.dart" ]

View file

@ -235,17 +235,14 @@
"isolate": {
"uri": "isolate/isolate.dart"
},
"js": {
"uri": "js/js.dart",
"patches": "_internal/wasm/lib/js_patch.dart"
},
"js_util": {
"uri": "js_util/js_util.dart",
"patches": "_internal/wasm/lib/js_util_patch.dart"
},
"js_util_wasm": {
"uri": "js_util/js_util_wasm.dart",
"patches": "_internal/wasm/lib/js_util_wasm_patch.dart"
},
"js_wasm": {
"uri": "js/js_wasm.dart"
},
"math": {
"uri": "math/math.dart",
"patches": "_internal/wasm/lib/math_patch.dart"

View file

@ -218,14 +218,12 @@ wasm:
uri: "html/dartium/nativewrappers.dart"
isolate:
uri: isolate/isolate.dart
js:
uri: js/js.dart
patches: _internal/wasm/lib/js_patch.dart
js_util:
uri: js_util/js_util.dart
patches: _internal/wasm/lib/js_util_patch.dart
js_util_wasm:
uri: js_util/js_util_wasm.dart
patches: _internal/wasm/lib/js_util_wasm_patch.dart
js_wasm:
uri: js/js_wasm.dart
math:
uri: math/math.dart
patches: _internal/wasm/lib/math_patch.dart

View file

@ -3,11 +3,10 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:js_util';
import 'dart:js_util_wasm';
import 'dart:js_wasm';
import 'dart:wasm';
import 'package:expect/expect.dart';
import 'package:js/js.dart';
@JS()
external void eval(String code);
@ -17,8 +16,7 @@ typedef SumStringCallback = String Function(String a, String b);
@JS()
@staticInterop
class DartFromJSCallbackHelper {
// TODO(joshualitt): Update [allowInterop] to return a function.
external factory DartFromJSCallbackHelper.factory(Object summer);
external factory DartFromJSCallbackHelper.factory(SumStringCallback summer);
}
extension DartFromJSCallbackHelperMethods on DartFromJSCallbackHelper {

View file

@ -3,9 +3,9 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:js_util';
import 'dart:js_wasm';
import 'package:expect/expect.dart';
import 'package:js/js.dart';
@JS()
external void eval(String code);

View file

@ -2,10 +2,8 @@
// 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_util_wasm';
import 'dart:js_wasm';
import 'package:expect/expect.dart';
import 'package:js/js.dart';
@JS()
external void eval(String code);