diff --git a/pkg/_js_interop_checks/lib/src/transformations/export_creator.dart b/pkg/_js_interop_checks/lib/src/transformations/export_creator.dart index caade5747ae..d49eaba7b8e 100644 --- a/pkg/_js_interop_checks/lib/src/transformations/export_creator.dart +++ b/pkg/_js_interop_checks/lib/src/transformations/export_creator.dart @@ -36,7 +36,7 @@ class ExportCreator extends Transformer { ExportCreator( this._typeEnvironment, this._diagnosticReporter, this._exportChecker) : _allowInterop = _typeEnvironment.coreTypes.index - .getTopLevelProcedure('dart:js', 'allowInterop'), + .getTopLevelProcedure('dart:js_util', 'allowInterop'), _createDartExport = _typeEnvironment.coreTypes.index .getTopLevelProcedure('dart:js_util', 'createDartExport'), _createStaticInteropMock = _typeEnvironment.coreTypes.index diff --git a/pkg/_js_interop_checks/lib/src/transformations/js_util_optimizer.dart b/pkg/_js_interop_checks/lib/src/transformations/js_util_optimizer.dart index b75da78d71f..eb49ccf9bb5 100644 --- a/pkg/_js_interop_checks/lib/src/transformations/js_util_optimizer.dart +++ b/pkg/_js_interop_checks/lib/src/transformations/js_util_optimizer.dart @@ -89,8 +89,8 @@ class JsUtilOptimizer extends Transformer { .getTopLevelProcedure('dart:js_util', '_setPropertyUnchecked'), _jsTarget = _coreTypes.index.getTopLevelProcedure('dart:_foreign_helper', 'JS'), - _allowInteropTarget = - _coreTypes.index.getTopLevelProcedure('dart:js', 'allowInterop'), + _allowInteropTarget = _coreTypes.index + .getTopLevelProcedure('dart:js_util', 'allowInterop'), _allowedInteropJsUtilTargets = _allowedInteropJsUtilMembers.map( (member) => _coreTypes.index.getTopLevelProcedure('dart:js_util', member)), diff --git a/pkg/compiler/lib/src/common/elements.dart b/pkg/compiler/lib/src/common/elements.dart index 1dbff8b97b2..03475b4b42d 100644 --- a/pkg/compiler/lib/src/common/elements.dart +++ b/pkg/compiler/lib/src/common/elements.dart @@ -139,8 +139,9 @@ abstract class CommonElements { late final LibraryEntity internalLibrary = _env.lookupLibrary(Uris.dart__internal, required: true)!; - /// The dart:js library. - late final LibraryEntity? dartJsLibrary = _env.lookupLibrary(Uris.dart_js); + /// The dart:js_util library. + late final LibraryEntity? dartJsUtilLibrary = + _env.lookupLibrary(Uris.dart_js_util); /// The package:js library. late final LibraryEntity? packageJsLibrary = @@ -1039,21 +1040,9 @@ abstract class CommonElements { : objectClass; } - // From package:js - late final FunctionEntity? jsAllowInterop1 = - _findLibraryMember(dartJsLibrary, 'allowInterop', required: false); - - // From dart:_js_annotations; - late final FunctionEntity? jsAllowInterop2 = _findLibraryMember( - dartJsAnnotationsLibrary, 'allowInterop', - required: false); - - /// Returns `true` if [function] is `allowInterop`. - /// - /// This function can come from either `package:js` or `dart:_js_annotations`. - bool isJsAllowInterop(FunctionEntity function) { - return function == jsAllowInterop1 || function == jsAllowInterop2; - } + // From dart:js_util + late final FunctionEntity? jsAllowInterop = + _findLibraryMember(dartJsUtilLibrary, 'allowInterop', required: false); bool isCreateInvocationMirrorHelper(MemberEntity member) { return member.isTopLevel && diff --git a/pkg/compiler/lib/src/common/names.dart b/pkg/compiler/lib/src/common/names.dart index abd2114d234..470f3f1200d 100644 --- a/pkg/compiler/lib/src/common/names.dart +++ b/pkg/compiler/lib/src/common/names.dart @@ -255,8 +255,8 @@ class Uris { static final Uri dart__js_shared_embedded_names = Uri(scheme: 'dart', path: '_js_shared_embedded_names'); - /// The URI for 'dart:js'. - static final Uri dart_js = Uri(scheme: 'dart', path: 'js'); + /// The URI for 'dart:js_util'. + static final Uri dart_js_util = Uri(scheme: 'dart', path: 'js_util'); /// The URI for 'package:js'. static final Uri package_js = Uri(scheme: 'package', path: 'js/js.dart'); diff --git a/pkg/compiler/lib/src/js_backend/backend_impact.dart b/pkg/compiler/lib/src/js_backend/backend_impact.dart index 3b3d4d23c58..1b9ab7b6171 100644 --- a/pkg/compiler/lib/src/js_backend/backend_impact.dart +++ b/pkg/compiler/lib/src/js_backend/backend_impact.dart @@ -399,8 +399,7 @@ class BackendImpacts { late final BackendImpact allowInterop = BackendImpact( staticUses: [ - _commonElements.jsAllowInterop1!, - _commonElements.jsAllowInterop2!, + _commonElements.jsAllowInterop!, ], features: EnumSet.fromValues([ BackendFeature.needToInitializeIsolateAffinityTag, diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart index 690022ee3ac..9a089cf0ad8 100644 --- a/pkg/compiler/lib/src/ssa/codegen.dart +++ b/pkg/compiler/lib/src/ssa/codegen.dart @@ -2066,8 +2066,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { List arguments = visitArguments(node.inputs, start: 0); - if (element == _commonElements.jsAllowInterop1 || - element == _commonElements.jsAllowInterop2) { + if (element == _commonElements.jsAllowInterop) { _nativeData.registerAllowInterop(); } diff --git a/pkg/compiler/test/impact/data/jsinterop.dart b/pkg/compiler/test/impact/data/jsinterop.dart index 65598fd359c..ba65d5dc54c 100644 --- a/pkg/compiler/test/impact/data/jsinterop.dart +++ b/pkg/compiler/test/impact/data/jsinterop.dart @@ -30,21 +30,9 @@ class JsInteropClass { /*member: JsInteropClass.:*/ external JsInteropClass(); - /*member: JsInteropClass.method: - type=[ - native:ApplicationCacheErrorEvent, - native:DomError, - native:DomException, - native:ErrorEvent, + /*member: JsInteropClass.method:type=[ native:GenericClass, - native:JsInteropClass, - native:MediaError, - native:NavigatorUserMediaError, - native:OverconstrainedError, - native:PositionError, - native:SensorErrorEvent, - native:SpeechRecognitionError] - */ + native:JsInteropClass]*/ @JS() external double method(); } diff --git a/pkg/dart2wasm/lib/js_runtime_generator.dart b/pkg/dart2wasm/lib/js_runtime_generator.dart index 2b85a307d39..fd8cd20d87a 100644 --- a/pkg/dart2wasm/lib/js_runtime_generator.dart +++ b/pkg/dart2wasm/lib/js_runtime_generator.dart @@ -163,8 +163,8 @@ class _JSLowerer extends Transformer { .getClass('dart:_js_helper', 'JSValue') .procedures .firstWhere((p) => p.name.text == 'unbox'), - _allowInteropTarget = - _coreTypes.index.getTopLevelProcedure('dart:js', 'allowInterop'), + _allowInteropTarget = _coreTypes.index + .getTopLevelProcedure('dart:js_util', 'allowInterop'), _inlineJSTarget = _coreTypes.index.getTopLevelProcedure('dart:_js_helper', 'JS'), _wasmExternRefClass = diff --git a/pkg/dart2wasm/lib/target.dart b/pkg/dart2wasm/lib/target.dart index eeb07e78ce9..617f592e21b 100644 --- a/pkg/dart2wasm/lib/target.dart +++ b/pkg/dart2wasm/lib/target.dart @@ -61,7 +61,6 @@ class WasmTarget extends Target { 'dart:typed_data', 'dart:nativewrappers', 'dart:io', - 'dart:js', 'dart:js_util', 'dart:wasm', 'dart:developer', @@ -73,7 +72,6 @@ class WasmTarget extends Target { 'dart:_js_interop', 'dart:collection', 'dart:typed_data', - 'dart:js', 'dart:js_util', 'dart:wasm', ]; diff --git a/pkg/dev_compiler/lib/src/kernel/js_interop.dart b/pkg/dev_compiler/lib/src/kernel/js_interop.dart index 16f1038a2de..b78ee59a29d 100644 --- a/pkg/dev_compiler/lib/src/kernel/js_interop.dart +++ b/pkg/dev_compiler/lib/src/kernel/js_interop.dart @@ -34,7 +34,7 @@ bool _isJSLibrary(Library library) => _isLibrary(library, [ bool isAllowInterop(Expression node) { if (node is StaticInvocation) { var target = node.target; - return _isLibrary(target.enclosingLibrary, ['dart:js']) && + return _isLibrary(target.enclosingLibrary, ['dart:js_util']) && target.name.text == 'allowInterop'; } return false; diff --git a/pkg/js/lib/js.dart b/pkg/js/lib/js.dart index b395efeac22..b6897c5f0f2 100644 --- a/pkg/js/lib/js.dart +++ b/pkg/js/lib/js.dart @@ -7,7 +7,7 @@ library js; import 'package:meta/meta.dart'; -export 'dart:js' show allowInterop, allowInteropCaptureThis; +export 'dart:js_util' show allowInterop, allowInteropCaptureThis; /// An annotation that indicates a library, class, or member is implemented /// directly in JavaScript. diff --git a/sdk/lib/_internal/js_dev_runtime/patch/js_allow_interop_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/js_allow_interop_patch.dart new file mode 100644 index 00000000000..b3bfee5219d --- /dev/null +++ b/sdk/lib/_internal/js_dev_runtime/patch/js_allow_interop_patch.dart @@ -0,0 +1,48 @@ +// Copyright (c) 2023, 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. + +// Patch file for dart:js_util library. +import 'dart:_foreign_helper' show JS; +import 'dart:_internal' show patch; +import 'dart:_runtime' as dart; + +Expando _interopExpando = Expando(); + +@patch +F allowInterop(F f) { + if (!dart.isDartFunction(f)) return f; + var ret = _interopExpando[f] as F?; + if (ret == null) { + ret = JS( + '', + 'function (...args) {' + ' return #(#, args);' + '}', + dart.dcall, + f); + _interopExpando[f] = ret; + } + return ret; +} + +Expando _interopCaptureThisExpando = Expando(); + +@patch +Function allowInteropCaptureThis(Function f) { + if (!dart.isDartFunction(f)) return f; + var ret = _interopCaptureThisExpando[f]; + if (ret == null) { + ret = JS( + '', + 'function(...arguments) {' + ' let args = [this];' + ' args.push.apply(args, arguments);' + ' return #(#, args);' + '}', + dart.dcall, + f); + _interopCaptureThisExpando[f] = ret; + } + return ret; +} diff --git a/sdk/lib/_internal/js_dev_runtime/patch/js_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/js_patch.dart index 2eda2b4fdfc..f9349796da0 100644 --- a/sdk/lib/_internal/js_dev_runtime/patch/js_patch.dart +++ b/sdk/lib/_internal/js_dev_runtime/patch/js_patch.dart @@ -404,43 +404,3 @@ T _putIfAbsent(Object weakMap, Object o, T getValue(Object o)) { // TODO(vsm): Static cast. Unnecessary? return JS('', '#', value); } - -Expando _interopExpando = Expando(); - -@patch -F allowInterop(F f) { - if (!dart.isDartFunction(f)) return f; - var ret = _interopExpando[f] as F?; - if (ret == null) { - ret = JS( - '', - 'function (...args) {' - ' return #(#, args);' - '}', - dart.dcall, - f); - _interopExpando[f] = ret; - } - return ret; -} - -Expando _interopCaptureThisExpando = Expando(); - -@patch -Function allowInteropCaptureThis(Function f) { - if (!dart.isDartFunction(f)) return f; - var ret = _interopCaptureThisExpando[f]; - if (ret == null) { - ret = JS( - '', - 'function(...arguments) {' - ' let args = [this];' - ' args.push.apply(args, arguments);' - ' return #(#, args);' - '}', - dart.dcall, - f); - _interopCaptureThisExpando[f] = ret; - } - return ret; -} diff --git a/sdk/lib/_internal/js_runtime/lib/js_allow_interop_patch.dart b/sdk/lib/_internal/js_runtime/lib/js_allow_interop_patch.dart new file mode 100644 index 00000000000..831cd4911b2 --- /dev/null +++ b/sdk/lib/_internal/js_runtime/lib/js_allow_interop_patch.dart @@ -0,0 +1,82 @@ +// Copyright (c) 2023, 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. + +// Patch file for dart:js_util library. + +import 'dart:_foreign_helper' show JS, DART_CLOSURE_TO_JS; +import 'dart:_interceptors' show DART_CLOSURE_PROPERTY_NAME; +import 'dart:_internal' show patch; +import 'dart:_js_helper' + show + isJSFunction, + JS_FUNCTION_PROPERTY_NAME, + JS_FUNCTION_PROPERTY_NAME_CAPTURE_THIS; + +_convertDartFunctionFast(Function f) { + var existing = JS('', '#.#', f, JS_FUNCTION_PROPERTY_NAME); + if (existing != null) return existing; + var ret = JS( + 'JavaScriptFunction', + ''' + function(_call, f) { + return function() { + return _call(f, Array.prototype.slice.apply(arguments)); + } + }(#, #) + ''', + DART_CLOSURE_TO_JS(_callDartFunctionFast), + f); + JS('', '#.# = #', ret, DART_CLOSURE_PROPERTY_NAME, f); + JS('', '#.# = #', f, JS_FUNCTION_PROPERTY_NAME, ret); + return ret; +} + +_convertDartFunctionFastCaptureThis(Function f) { + var existing = JS('', '#.#', f, JS_FUNCTION_PROPERTY_NAME_CAPTURE_THIS); + if (existing != null) return existing; + var ret = JS( + 'JavaScriptFunction', + ''' + function(_call, f) { + return function() { + return _call(f, this,Array.prototype.slice.apply(arguments)); + } + }(#, #) + ''', + DART_CLOSURE_TO_JS(_callDartFunctionFastCaptureThis), + f); + JS('', '#.# = #', ret, DART_CLOSURE_PROPERTY_NAME, f); + JS('', '#.# = #', f, JS_FUNCTION_PROPERTY_NAME_CAPTURE_THIS, ret); + return ret; +} + +_callDartFunctionFast(callback, List arguments) { + return Function.apply(callback, arguments); +} + +_callDartFunctionFastCaptureThis(callback, self, List arguments) { + return Function.apply(callback, [self]..addAll(arguments)); +} + +@patch +F allowInterop(F f) { + if (isJSFunction(f)) { + // Already supports interop, just use the existing function. + return f; + } else { + return _convertDartFunctionFast(f); + } +} + +@patch +Function allowInteropCaptureThis(Function f) { + if (isJSFunction(f)) { + // Behavior when the function is already a JS function is unspecified. + throw ArgumentError( + "Function is already a JS function so cannot capture this."); + return f; + } else { + return _convertDartFunctionFastCaptureThis(f); + } +} diff --git a/sdk/lib/_internal/js_runtime/lib/js_helper.dart b/sdk/lib/_internal/js_runtime/lib/js_helper.dart index cefeb714965..38f3c62f5c6 100644 --- a/sdk/lib/_internal/js_runtime/lib/js_helper.dart +++ b/sdk/lib/_internal/js_runtime/lib/js_helper.dart @@ -82,6 +82,9 @@ part 'string_helper.dart'; part 'linked_hash_map.dart'; part 'records.dart'; +const JS_FUNCTION_PROPERTY_NAME = r'$dart_jsFunction'; +const JS_FUNCTION_PROPERTY_NAME_CAPTURE_THIS = r'_$dart_jsFunctionCaptureThis'; + /// Marks the internal map in dart2js, so that internal libraries can is-check /// them. abstract class InternalMap {} diff --git a/sdk/lib/_internal/js_runtime/lib/js_patch.dart b/sdk/lib/_internal/js_runtime/lib/js_patch.dart index ede166822ac..ff574c64b1d 100644 --- a/sdk/lib/_internal/js_runtime/lib/js_patch.dart +++ b/sdk/lib/_internal/js_runtime/lib/js_patch.dart @@ -9,7 +9,12 @@ import 'dart:typed_data' show TypedData; import 'dart:_foreign_helper' show JS, DART_CLOSURE_TO_JS; import 'dart:_interceptors' show DART_CLOSURE_PROPERTY_NAME; import 'dart:_internal' show patch; -import 'dart:_js_helper' show Primitives, getIsolateAffinityTag, isJSFunction; +import 'dart:_js_helper' + show + Primitives, + getIsolateAffinityTag, + isJSFunction, + JS_FUNCTION_PROPERTY_NAME; import 'dart:_js' show isBrowserObject, convertFromBrowserObject; @patch @@ -370,8 +375,6 @@ final String _DART_OBJECT_PROPERTY_NAME = // property added to a JS object referencing its Dart-side JsObject proxy const _JS_OBJECT_PROPERTY_NAME = r'_$dart_jsObject'; -const _JS_FUNCTION_PROPERTY_NAME = r'$dart_jsFunction'; -const _JS_FUNCTION_PROPERTY_NAME_CAPTURE_THIS = r'_$dart_jsFunctionCaptureThis'; @pragma('dart2js:tryInline') JsObject _castToJsObject(o) => JS('', '#', o); @@ -431,7 +434,7 @@ Object? _convertToJS(Object? o) { return Primitives.lazyAsJsDate(o); } if (o is Function) { - return _getJsProxy(o, _JS_FUNCTION_PROPERTY_NAME, (o) { + return _getJsProxy(o, JS_FUNCTION_PROPERTY_NAME, (o) { var jsFunction = _convertDartFunction(o); // set a property on the JS closure referencing the Dart closure _defineProperty(jsFunction, DART_CLOSURE_PROPERTY_NAME, o); @@ -502,71 +505,3 @@ Object _getDartProxy(o, String propertyName, JsObject createProxy(o)) { } return dartProxy; } - -_convertDartFunctionFast(Function f) { - var existing = JS('', '#.#', f, _JS_FUNCTION_PROPERTY_NAME); - if (existing != null) return existing; - var ret = JS( - 'JavaScriptFunction', - ''' - function(_call, f) { - return function() { - return _call(f, Array.prototype.slice.apply(arguments)); - } - }(#, #) - ''', - DART_CLOSURE_TO_JS(_callDartFunctionFast), - f); - JS('', '#.# = #', ret, DART_CLOSURE_PROPERTY_NAME, f); - JS('', '#.# = #', f, _JS_FUNCTION_PROPERTY_NAME, ret); - return ret; -} - -_convertDartFunctionFastCaptureThis(Function f) { - var existing = JS('', '#.#', f, _JS_FUNCTION_PROPERTY_NAME_CAPTURE_THIS); - if (existing != null) return existing; - var ret = JS( - 'JavaScriptFunction', - ''' - function(_call, f) { - return function() { - return _call(f, this,Array.prototype.slice.apply(arguments)); - } - }(#, #) - ''', - DART_CLOSURE_TO_JS(_callDartFunctionFastCaptureThis), - f); - JS('', '#.# = #', ret, DART_CLOSURE_PROPERTY_NAME, f); - JS('', '#.# = #', f, _JS_FUNCTION_PROPERTY_NAME_CAPTURE_THIS, ret); - return ret; -} - -_callDartFunctionFast(callback, List arguments) { - return Function.apply(callback, arguments); -} - -_callDartFunctionFastCaptureThis(callback, self, List arguments) { - return Function.apply(callback, [self]..addAll(arguments)); -} - -@patch -F allowInterop(F f) { - if (isJSFunction(f)) { - // Already supports interop, just use the existing function. - return f; - } else { - return _convertDartFunctionFast(f); - } -} - -@patch -Function allowInteropCaptureThis(Function f) { - if (isJSFunction(f)) { - // Behavior when the function is already a JS function is unspecified. - throw ArgumentError( - "Function is already a JS function so cannot capture this."); - return f; - } else { - return _convertDartFunctionFastCaptureThis(f); - } -} diff --git a/sdk/lib/_internal/js_shared/lib/js_util_patch.dart b/sdk/lib/_internal/js_shared/lib/js_util_patch.dart index d2b55952b14..fe45f9b822c 100644 --- a/sdk/lib/_internal/js_shared/lib/js_util_patch.dart +++ b/sdk/lib/_internal/js_shared/lib/js_util_patch.dart @@ -8,7 +8,6 @@ import 'dart:_js_helper' show convertDartClosureToJS, assertInterop, assertInteropArgs; import 'dart:collection' show HashMap; import 'dart:async' show Completer; -import 'dart:js_util'; @patch dynamic jsify(Object object) { diff --git a/sdk/lib/_internal/wasm/lib/js_patch.dart b/sdk/lib/_internal/wasm/lib/js_patch.dart index fde0468e883..d6aefadd754 100644 --- a/sdk/lib/_internal/wasm/lib/js_patch.dart +++ b/sdk/lib/_internal/wasm/lib/js_patch.dart @@ -113,10 +113,3 @@ class JsArray extends JsObject with ListMixin { @patch void sort([int compare(E a, E b)?]) => throw UnimplementedError(); } - -/// This will be lowered to a call to `_wrapDartCallback`. -@patch -F allowInterop(F f) => throw UnimplementedError(); - -@patch -Function allowInteropCaptureThis(Function f) => throw UnimplementedError(); diff --git a/sdk/lib/_internal/wasm/lib/js_util_patch.dart b/sdk/lib/_internal/wasm/lib/js_util_patch.dart index 3dfc1024fe5..a14a25ee61d 100644 --- a/sdk/lib/_internal/wasm/lib/js_util_patch.dart +++ b/sdk/lib/_internal/wasm/lib/js_util_patch.dart @@ -150,10 +150,10 @@ typedef _PromiseFailureFunc = void Function(Object? error); Future promiseToFuture(Object jsPromise) { Completer completer = Completer(); - final success = js.allowInterop<_PromiseSuccessFunc>((r) { + final success = allowInterop<_PromiseSuccessFunc>((r) { return completer.complete(r as FutureOr?); }); - final error = js.allowInterop<_PromiseFailureFunc>((e) { + final error = allowInterop<_PromiseFailureFunc>((e) { // Note that `completeError` expects a non-nullable error regardless of // whether null-safety is enabled, so a `NullRejectionException` is always // provided if the error is `null` or `undefined`. @@ -257,3 +257,10 @@ Object? dartify(Object? object) { return convert(object); } + +/// This will be lowered to a a call to `_wrapDartCallback`. +@patch +F allowInterop(F f) => throw UnimplementedError(); + +@patch +Function allowInteropCaptureThis(Function f) => throw UnimplementedError(); diff --git a/sdk/lib/js/_js_annotations.dart b/sdk/lib/js/_js_annotations.dart index 415547052d2..f053d6e90d1 100644 --- a/sdk/lib/js/_js_annotations.dart +++ b/sdk/lib/js/_js_annotations.dart @@ -7,7 +7,7 @@ // https://github.com/dart-lang/sdk/blob/master/pkg/js/lib/js.dart library _js_annotations; -export 'dart:js' show allowInterop, allowInteropCaptureThis; +export 'dart:js_util' show allowInterop, allowInteropCaptureThis; class JS { final String? name; diff --git a/sdk/lib/js/js.dart b/sdk/lib/js/js.dart index 7f2921e1299..4fba6a40bb6 100644 --- a/sdk/lib/js/js.dart +++ b/sdk/lib/js/js.dart @@ -86,6 +86,8 @@ library dart.js; import 'dart:collection' show ListMixin; +export 'dart:js_util' show allowInterop, allowInteropCaptureThis; + /// The JavaScript global object, usually `window`. external JsObject get context; @@ -209,25 +211,3 @@ class JsArray extends JsObject with ListMixin { external void sort([int compare(E a, E b)?]); } - -/// Returns a wrapper around function [f] that can be called from JavaScript -/// using `package:js` JavaScript interop. -/// -/// The calling conventions in Dart2Js differ from JavaScript and so, by -/// default, it is not possible to call a Dart function directly. Wrapping with -/// `allowInterop` creates a function that can be called from JavaScript or -/// Dart. The semantics of the wrapped function are still more strict than -/// JavaScript, and the function will throw if called with too many or too few -/// arguments. -/// -/// Calling this method repeatedly on a function will return the same result. -external F allowInterop(F f); - -/// Returns a wrapper around function [f] that can be called from JavaScript -/// using `package:js` JavaScript interop, passing JavaScript `this` as the first -/// argument. -/// -/// See [allowInterop]. -/// -/// When called from Dart, `null` will be passed as the first argument. -external Function allowInteropCaptureThis(Function f); diff --git a/sdk/lib/js_util/js_util.dart b/sdk/lib/js_util/js_util.dart index 75c9cf0e00f..513daafd856 100644 --- a/sdk/lib/js_util/js_util.dart +++ b/sdk/lib/js_util/js_util.dart @@ -256,3 +256,25 @@ external T createStaticInteropMock( /// Expect.isTrue(counter.stringify(), export.stringify()); /// ``` external Object createDartExport(T dartObject); + +/// Returns a wrapper around function [f] that can be called from JavaScript +/// using `package:js` JavaScript interop. +/// +/// The calling conventions in Dart web backends differ from JavaScript and so, +/// by default, it is not possible to call a Dart function directly. Wrapping +/// with `allowInterop` creates a function that can be called from JavaScript or +/// Dart. The semantics of the wrapped function are still more strict than +/// JavaScript, and the function will throw if called with too many or too few +/// arguments. +/// +/// Calling this method repeatedly on a function will return the same result. +external F allowInterop(F f); + +/// Returns a wrapper around function [f] that can be called from JavaScript +/// using `package:js` JavaScript interop, passing JavaScript `this` as the +/// first argument. +/// +/// See [allowInterop]. +/// +/// When called from Dart, `null` will be passed as the first argument. +external Function allowInteropCaptureThis(Function f); diff --git a/sdk/lib/libraries.json b/sdk/lib/libraries.json index b114c00a1ee..3829332c0ac 100644 --- a/sdk/lib/libraries.json +++ b/sdk/lib/libraries.json @@ -334,7 +334,10 @@ }, "js_util": { "uri": "js_util/js_util.dart", - "patches": "_internal/js_shared/lib/js_util_patch.dart" + "patches": [ + "_internal/js_shared/lib/js_util_patch.dart", + "_internal/js_runtime/lib/js_allow_interop_patch.dart" + ] }, "math": { "uri": "math/math.dart", @@ -506,7 +509,10 @@ }, "js_util": { "uri": "js_util/js_util.dart", - "patches": "_internal/js_shared/lib/js_util_patch.dart" + "patches": [ + "_internal/js_shared/lib/js_util_patch.dart", + "_internal/js_dev_runtime/patch/js_allow_interop_patch.dart" + ] }, "svg": { "uri": "svg/dart2js/svg_dart2js.dart" diff --git a/sdk/lib/libraries.yaml b/sdk/lib/libraries.yaml index 474aa74a05d..1f89f2183d3 100644 --- a/sdk/lib/libraries.yaml +++ b/sdk/lib/libraries.yaml @@ -287,7 +287,9 @@ _dart2js_common: js_util: uri: "js_util/js_util.dart" - patches: "_internal/js_shared/lib/js_util_patch.dart" + patches: + - "_internal/js_shared/lib/js_util_patch.dart" + - "_internal/js_runtime/lib/js_allow_interop_patch.dart" math: uri: "math/math.dart" @@ -457,7 +459,9 @@ dartdevc: js_util: uri: "js_util/js_util.dart" - patches: "_internal/js_shared/lib/js_util_patch.dart" + patches: + - "_internal/js_shared/lib/js_util_patch.dart" + - "_internal/js_dev_runtime/patch/js_allow_interop_patch.dart" svg: uri: "svg/dart2js/svg_dart2js.dart"