Skip to content

Commit 3fd96e2

Browse files
joshualittCommit Bot
authored and
Commit Bot
committed
[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 <[email protected]> Commit-Queue: Joshua Litt <[email protected]>
1 parent 3e17635 commit 3fd96e2

File tree

12 files changed

+170
-59
lines changed

12 files changed

+170
-59
lines changed

pkg/_js_interop_checks/lib/src/js_interop.dart

+1-3
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,10 @@ List<String> getNativeNames(Annotatable a) {
6060
}
6161

6262
final _packageJs = Uri.parse('package:js/js.dart');
63-
final _jsWasm = Uri.parse('dart:js_wasm');
6463
final _internalJs = Uri.parse('dart:_js_annotations');
6564
final _jsHelper = Uri.parse('dart:_js_helper');
6665

67-
bool _isAnyInteropUri(Uri uri) =>
68-
uri == _packageJs || uri == _internalJs || uri == _jsWasm;
66+
bool _isAnyInteropUri(Uri uri) => uri == _packageJs || uri == _internalJs;
6967

7068
/// Returns true if [value] is the interop annotation whose class is
7169
/// [annotationClassName] from `package:js` or from `dart:_js_annotations`.

pkg/_js_interop_checks/lib/src/transformations/js_util_wasm_optimizer.dart

+7-5
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,11 @@ class JsUtilWasmOptimizer extends Transformer {
7878
_jsifyRawTarget = _coreTypes.index
7979
.getTopLevelProcedure('dart:_js_helper', 'jsifyRaw'),
8080
_wrapDartCallbackTarget = _coreTypes.index
81-
.getTopLevelProcedure('dart:js_util_wasm', '_wrapDartCallback'),
81+
.getTopLevelProcedure('dart:_js_helper', '_wrapDartCallback'),
8282
_newObjectTarget =
8383
_coreTypes.index.getTopLevelProcedure('dart:js_util', 'newObject'),
84-
_allowInteropTarget = _coreTypes.index
85-
.getTopLevelProcedure('dart:js_util_wasm', 'allowInterop'),
84+
_allowInteropTarget =
85+
_coreTypes.index.getTopLevelProcedure('dart:js', 'allowInterop'),
8686
_wasmAnyRefClass = _coreTypes.index.getClass('dart:wasm', 'WasmAnyRef'),
8787
_objectClass = _coreTypes.objectClass,
8888
_pragmaClass = _coreTypes.pragmaClass,
@@ -283,8 +283,10 @@ class JsUtilWasmOptimizer extends Transformer {
283283
StaticInvocation _allowInterop(
284284
Procedure node, FunctionType type, Expression argument) {
285285
String callbackTrampolineName = _createCallbackTrampoline(node, type);
286-
return StaticInvocation(_wrapDartCallbackTarget,
287-
Arguments([argument, StringLiteral(callbackTrampolineName)]));
286+
return StaticInvocation(
287+
_wrapDartCallbackTarget,
288+
Arguments([argument, StringLiteral(callbackTrampolineName)],
289+
types: [type]));
288290
}
289291

290292
StaticGet get _globalThis => StaticGet(_globalThisMember);

pkg/dart2wasm/lib/target.dart

+3-5
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,8 @@ class WasmTarget extends Target {
5050
'dart:_js_helper',
5151
'dart:typed_data',
5252
'dart:nativewrappers',
53+
'dart:js',
5354
'dart:js_util',
54-
'dart:js_util_wasm',
55-
'dart:js_wasm',
5655
'dart:wasm',
5756
'dart:developer',
5857
];
@@ -62,9 +61,8 @@ class WasmTarget extends Target {
6261
'dart:_js_helper',
6362
'dart:collection',
6463
'dart:typed_data',
64+
'dart:js',
6565
'dart:js_util',
66-
'dart:js_util_wasm',
67-
'dart:js_wasm',
6866
'dart:wasm',
6967
];
7068

@@ -107,7 +105,7 @@ class WasmTarget extends Target {
107105
ChangedStructureNotifier? changedStructureNotifier}) {
108106
List<Library>? transitiveImportingJSInterop =
109107
jsInteropHelper.calculateTransitiveImportsOfJsInteropIfUsed(
110-
component, Uri.parse("dart:js_wasm"));
108+
component, Uri.parse("package:js/js.dart"));
111109
if (transitiveImportingJSInterop == null) {
112110
logger?.call("Skipped JS interop transformations");
113111
} else {

sdk/lib/_internal/wasm/lib/js_helper.dart

+27-1
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,21 @@ external WasmAnyRef? setPropertyRaw(
8787
external WasmAnyRef? callMethodVarArgsRaw(
8888
WasmAnyRef o, WasmAnyRef method, WasmAnyRef? args);
8989

90+
// Currently, `allowInterop` returns a Function type. This is unfortunate for
91+
// Dart2wasm because it means arbitrary Dart functions can flow to JS util
92+
// calls. Our only solutions is to cache every function called with
93+
// `allowInterop` and to replace them with the wrapped variant when they flow
94+
// to JS.
95+
// NOTE: We are not currently replacing functions returned from JS.
96+
Map<Function, JSValue> functionToJSWrapper = {};
97+
9098
WasmAnyRef? jsifyRaw(Object? object) {
9199
if (object == null) {
92100
return null;
101+
} else if (object is Function) {
102+
assert(functionToJSWrapper.containsKey(object),
103+
'Must call `allowInterop` on functions before they flow to JS');
104+
return functionToJSWrapper[object]?.toAnyRef();
93105
} else if (object is JSValue) {
94106
return object.toAnyRef();
95107
} else if (object is String) {
@@ -101,7 +113,21 @@ WasmAnyRef? jsifyRaw(Object? object) {
101113
}
102114
}
103115

104-
/// js_util_wasm methods used by the wasm runtime.
116+
@pragma("wasm:import", "dart2wasm.wrapDartCallback")
117+
external WasmAnyRef _wrapDartCallbackRaw(
118+
WasmAnyRef callback, WasmAnyRef trampolineName);
119+
120+
F _wrapDartCallback<F extends Function>(F f, String trampolineName) {
121+
if (functionToJSWrapper.containsKey(f)) {
122+
return f;
123+
}
124+
JSValue wrappedFunction = JSValue(_wrapDartCallbackRaw(
125+
f.toJS().toAnyRef(), trampolineName.toJS().toAnyRef()));
126+
functionToJSWrapper[f] = wrappedFunction;
127+
return f;
128+
}
129+
130+
/// Methods used by the wasm runtime.
105131
@pragma("wasm:export", "\$listLength")
106132
double _listLength(List list) => list.length.toDouble();
107133

+120
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
// This library is only supported on dart2wasm because of [allowInterop].
6+
7+
library dart.js;
8+
9+
import 'dart:_internal' show patch;
10+
import 'dart:_js_helper';
11+
import 'dart:collection' show ListMixin;
12+
import 'dart:wasm';
13+
14+
@patch
15+
JsObject get context => throw UnimplementedError;
16+
17+
@patch
18+
class JsObject {
19+
// No argument empty constructor to support inheritance.
20+
JsObject._() {
21+
throw UnimplementedError;
22+
}
23+
24+
@patch
25+
factory JsObject(JsFunction constructor, [List? arguments]) =>
26+
throw UnimplementedError;
27+
28+
@patch
29+
factory JsObject.fromBrowserObject(Object object) => throw UnimplementedError;
30+
31+
@patch
32+
factory JsObject.jsify(Object object) => throw UnimplementedError;
33+
34+
@patch
35+
dynamic operator [](Object property) => throw UnimplementedError;
36+
37+
@patch
38+
void operator []=(Object property, Object? value) => throw UnimplementedError;
39+
40+
@patch
41+
bool operator ==(Object other) => throw UnimplementedError;
42+
43+
@patch
44+
bool hasProperty(Object property) => throw UnimplementedError;
45+
46+
@patch
47+
void deleteProperty(Object property) => throw UnimplementedError;
48+
49+
@patch
50+
bool instanceof(JsFunction type) => throw UnimplementedError;
51+
52+
@patch
53+
String toString() => throw UnimplementedError;
54+
55+
@patch
56+
dynamic callMethod(Object method, [List? args]) => throw UnimplementedError;
57+
}
58+
59+
@patch
60+
class JsFunction extends JsObject {
61+
@patch
62+
factory JsFunction.withThis(Function f) => throw UnimplementedError;
63+
64+
@patch
65+
dynamic apply(List args, {thisArg}) => throw UnimplementedError;
66+
}
67+
68+
@patch
69+
class JsArray<E> extends JsObject with ListMixin<E> {
70+
@patch
71+
factory JsArray() => throw UnimplementedError;
72+
73+
@patch
74+
factory JsArray.from(Iterable<E> other) => throw UnimplementedError;
75+
76+
@patch
77+
E operator [](Object index) => throw UnimplementedError;
78+
79+
@patch
80+
void operator []=(Object index, E value) => throw UnimplementedError;
81+
82+
@patch
83+
int get length => throw UnimplementedError;
84+
85+
@patch
86+
void set length(int length) => throw UnimplementedError;
87+
88+
@patch
89+
void add(E value) => throw UnimplementedError;
90+
91+
@patch
92+
void addAll(Iterable<E> iterable) => throw UnimplementedError;
93+
94+
@patch
95+
void insert(int index, E element) => throw UnimplementedError;
96+
97+
@patch
98+
E removeAt(int index) => throw UnimplementedError;
99+
100+
@patch
101+
E removeLast() => throw UnimplementedError;
102+
103+
@patch
104+
void removeRange(int start, int end) => throw UnimplementedError;
105+
106+
@patch
107+
void setRange(int start, int end, Iterable<E> iterable,
108+
[int skipCount = 0]) =>
109+
throw UnimplementedError;
110+
111+
@patch
112+
void sort([int compare(E a, E b)?]) => throw UnimplementedError;
113+
}
114+
115+
/// This will be lowered to a a call to `_wrapDartCallback`.
116+
@patch
117+
F allowInterop<F extends Function>(F f) => throw UnimplementedError;
118+
119+
@patch
120+
Function allowInteropCaptureThis(Function f) => throw UnimplementedError;

sdk/lib/_internal/wasm/lib/js_util_wasm_patch.dart

-21
This file was deleted.

sdk/lib/js_util/js_util_sources.gni

+1-4
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,4 @@
22
# for details. All rights reserved. Use of this source code is governed by a
33
# BSD-style license that can be found in the LICENSE file.
44

5-
js_util_sdk_sources = [
6-
"js_util.dart",
7-
"js_util_wasm.dart",
8-
]
5+
js_util_sdk_sources = [ "js_util.dart" ]

sdk/lib/libraries.json

+4-7
Original file line numberDiff line numberDiff line change
@@ -235,17 +235,14 @@
235235
"isolate": {
236236
"uri": "isolate/isolate.dart"
237237
},
238+
"js": {
239+
"uri": "js/js.dart",
240+
"patches": "_internal/wasm/lib/js_patch.dart"
241+
},
238242
"js_util": {
239243
"uri": "js_util/js_util.dart",
240244
"patches": "_internal/wasm/lib/js_util_patch.dart"
241245
},
242-
"js_util_wasm": {
243-
"uri": "js_util/js_util_wasm.dart",
244-
"patches": "_internal/wasm/lib/js_util_wasm_patch.dart"
245-
},
246-
"js_wasm": {
247-
"uri": "js/js_wasm.dart"
248-
},
249246
"math": {
250247
"uri": "math/math.dart",
251248
"patches": "_internal/wasm/lib/math_patch.dart"

sdk/lib/libraries.yaml

+3-5
Original file line numberDiff line numberDiff line change
@@ -218,14 +218,12 @@ wasm:
218218
uri: "html/dartium/nativewrappers.dart"
219219
isolate:
220220
uri: isolate/isolate.dart
221+
js:
222+
uri: js/js.dart
223+
patches: _internal/wasm/lib/js_patch.dart
221224
js_util:
222225
uri: js_util/js_util.dart
223226
patches: _internal/wasm/lib/js_util_patch.dart
224-
js_util_wasm:
225-
uri: js_util/js_util_wasm.dart
226-
patches: _internal/wasm/lib/js_util_wasm_patch.dart
227-
js_wasm:
228-
uri: js/js_wasm.dart
229227
math:
230228
uri: math/math.dart
231229
patches: _internal/wasm/lib/math_patch.dart

tests/web/wasm/callback_test.dart

+2-4
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,10 @@
33
// BSD-style license that can be found in the LICENSE file.
44

55
import 'dart:js_util';
6-
import 'dart:js_util_wasm';
7-
import 'dart:js_wasm';
86
import 'dart:wasm';
97

108
import 'package:expect/expect.dart';
9+
import 'package:js/js.dart';
1110

1211
@JS()
1312
external void eval(String code);
@@ -17,8 +16,7 @@ typedef SumStringCallback = String Function(String a, String b);
1716
@JS()
1817
@staticInterop
1918
class DartFromJSCallbackHelper {
20-
// TODO(joshualitt): Update [allowInterop] to return a function.
21-
external factory DartFromJSCallbackHelper.factory(Object summer);
19+
external factory DartFromJSCallbackHelper.factory(SumStringCallback summer);
2220
}
2321

2422
extension DartFromJSCallbackHelperMethods on DartFromJSCallbackHelper {

tests/web/wasm/js_util_test.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
// BSD-style license that can be found in the LICENSE file.
44

55
import 'dart:js_util';
6-
import 'dart:js_wasm';
76

87
import 'package:expect/expect.dart';
8+
import 'package:js/js.dart';
99

1010
@JS()
1111
external void eval(String code);

tests/web/wasm/static_interop_test.dart

+1-3
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5-
import 'dart:js_util_wasm';
6-
import 'dart:js_wasm';
7-
85
import 'package:expect/expect.dart';
6+
import 'package:js/js.dart';
97

108
@JS()
119
external void eval(String code);

0 commit comments

Comments
 (0)