mirror of
https://github.com/dart-lang/sdk
synced 2024-07-20 07:26:23 +00:00
[js] Move allowInterop
functions to dart:js_util
.
CoreLibraryReviewExempt: Has core library owners approval. Change-Id: Iea2f2e707c69c9082e158b48b50dcaf4a7b01067 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/279740 Reviewed-by: Ömer Ağacan <omersa@google.com> Reviewed-by: Sigmund Cherem <sigmund@google.com> Reviewed-by: Srujan Gaddam <srujzs@google.com> Commit-Queue: Joshua Litt <joshualitt@google.com>
This commit is contained in:
parent
55e0784a62
commit
bd79be0e19
|
@ -36,7 +36,7 @@ class ExportCreator extends Transformer {
|
||||||
ExportCreator(
|
ExportCreator(
|
||||||
this._typeEnvironment, this._diagnosticReporter, this._exportChecker)
|
this._typeEnvironment, this._diagnosticReporter, this._exportChecker)
|
||||||
: _allowInterop = _typeEnvironment.coreTypes.index
|
: _allowInterop = _typeEnvironment.coreTypes.index
|
||||||
.getTopLevelProcedure('dart:js', 'allowInterop'),
|
.getTopLevelProcedure('dart:js_util', 'allowInterop'),
|
||||||
_createDartExport = _typeEnvironment.coreTypes.index
|
_createDartExport = _typeEnvironment.coreTypes.index
|
||||||
.getTopLevelProcedure('dart:js_util', 'createDartExport'),
|
.getTopLevelProcedure('dart:js_util', 'createDartExport'),
|
||||||
_createStaticInteropMock = _typeEnvironment.coreTypes.index
|
_createStaticInteropMock = _typeEnvironment.coreTypes.index
|
||||||
|
|
|
@ -89,8 +89,8 @@ class JsUtilOptimizer extends Transformer {
|
||||||
.getTopLevelProcedure('dart:js_util', '_setPropertyUnchecked'),
|
.getTopLevelProcedure('dart:js_util', '_setPropertyUnchecked'),
|
||||||
_jsTarget =
|
_jsTarget =
|
||||||
_coreTypes.index.getTopLevelProcedure('dart:_foreign_helper', 'JS'),
|
_coreTypes.index.getTopLevelProcedure('dart:_foreign_helper', 'JS'),
|
||||||
_allowInteropTarget =
|
_allowInteropTarget = _coreTypes.index
|
||||||
_coreTypes.index.getTopLevelProcedure('dart:js', 'allowInterop'),
|
.getTopLevelProcedure('dart:js_util', 'allowInterop'),
|
||||||
_allowedInteropJsUtilTargets = _allowedInteropJsUtilMembers.map(
|
_allowedInteropJsUtilTargets = _allowedInteropJsUtilMembers.map(
|
||||||
(member) =>
|
(member) =>
|
||||||
_coreTypes.index.getTopLevelProcedure('dart:js_util', member)),
|
_coreTypes.index.getTopLevelProcedure('dart:js_util', member)),
|
||||||
|
|
|
@ -139,8 +139,9 @@ abstract class CommonElements {
|
||||||
late final LibraryEntity internalLibrary =
|
late final LibraryEntity internalLibrary =
|
||||||
_env.lookupLibrary(Uris.dart__internal, required: true)!;
|
_env.lookupLibrary(Uris.dart__internal, required: true)!;
|
||||||
|
|
||||||
/// The dart:js library.
|
/// The dart:js_util library.
|
||||||
late final LibraryEntity? dartJsLibrary = _env.lookupLibrary(Uris.dart_js);
|
late final LibraryEntity? dartJsUtilLibrary =
|
||||||
|
_env.lookupLibrary(Uris.dart_js_util);
|
||||||
|
|
||||||
/// The package:js library.
|
/// The package:js library.
|
||||||
late final LibraryEntity? packageJsLibrary =
|
late final LibraryEntity? packageJsLibrary =
|
||||||
|
@ -1039,21 +1040,9 @@ abstract class CommonElements {
|
||||||
: objectClass;
|
: objectClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
// From package:js
|
// From dart:js_util
|
||||||
late final FunctionEntity? jsAllowInterop1 =
|
late final FunctionEntity? jsAllowInterop =
|
||||||
_findLibraryMember(dartJsLibrary, 'allowInterop', required: false);
|
_findLibraryMember(dartJsUtilLibrary, '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;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isCreateInvocationMirrorHelper(MemberEntity member) {
|
bool isCreateInvocationMirrorHelper(MemberEntity member) {
|
||||||
return member.isTopLevel &&
|
return member.isTopLevel &&
|
||||||
|
|
|
@ -255,8 +255,8 @@ class Uris {
|
||||||
static final Uri dart__js_shared_embedded_names =
|
static final Uri dart__js_shared_embedded_names =
|
||||||
Uri(scheme: 'dart', path: '_js_shared_embedded_names');
|
Uri(scheme: 'dart', path: '_js_shared_embedded_names');
|
||||||
|
|
||||||
/// The URI for 'dart:js'.
|
/// The URI for 'dart:js_util'.
|
||||||
static final Uri dart_js = Uri(scheme: 'dart', path: 'js');
|
static final Uri dart_js_util = Uri(scheme: 'dart', path: 'js_util');
|
||||||
|
|
||||||
/// The URI for 'package:js'.
|
/// The URI for 'package:js'.
|
||||||
static final Uri package_js = Uri(scheme: 'package', path: 'js/js.dart');
|
static final Uri package_js = Uri(scheme: 'package', path: 'js/js.dart');
|
||||||
|
|
|
@ -399,8 +399,7 @@ class BackendImpacts {
|
||||||
|
|
||||||
late final BackendImpact allowInterop = BackendImpact(
|
late final BackendImpact allowInterop = BackendImpact(
|
||||||
staticUses: [
|
staticUses: [
|
||||||
_commonElements.jsAllowInterop1!,
|
_commonElements.jsAllowInterop!,
|
||||||
_commonElements.jsAllowInterop2!,
|
|
||||||
],
|
],
|
||||||
features: EnumSet<BackendFeature>.fromValues([
|
features: EnumSet<BackendFeature>.fromValues([
|
||||||
BackendFeature.needToInitializeIsolateAffinityTag,
|
BackendFeature.needToInitializeIsolateAffinityTag,
|
||||||
|
|
|
@ -2066,8 +2066,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
||||||
|
|
||||||
List<js.Expression> arguments = visitArguments(node.inputs, start: 0);
|
List<js.Expression> arguments = visitArguments(node.inputs, start: 0);
|
||||||
|
|
||||||
if (element == _commonElements.jsAllowInterop1 ||
|
if (element == _commonElements.jsAllowInterop) {
|
||||||
element == _commonElements.jsAllowInterop2) {
|
|
||||||
_nativeData.registerAllowInterop();
|
_nativeData.registerAllowInterop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,21 +30,9 @@ class JsInteropClass {
|
||||||
/*member: JsInteropClass.:*/
|
/*member: JsInteropClass.:*/
|
||||||
external JsInteropClass();
|
external JsInteropClass();
|
||||||
|
|
||||||
/*member: JsInteropClass.method:
|
/*member: JsInteropClass.method:type=[
|
||||||
type=[
|
|
||||||
native:ApplicationCacheErrorEvent,
|
|
||||||
native:DomError,
|
|
||||||
native:DomException,
|
|
||||||
native:ErrorEvent,
|
|
||||||
native:GenericClass<dynamic>,
|
native:GenericClass<dynamic>,
|
||||||
native:JsInteropClass,
|
native:JsInteropClass]*/
|
||||||
native:MediaError,
|
|
||||||
native:NavigatorUserMediaError,
|
|
||||||
native:OverconstrainedError,
|
|
||||||
native:PositionError,
|
|
||||||
native:SensorErrorEvent,
|
|
||||||
native:SpeechRecognitionError]
|
|
||||||
*/
|
|
||||||
@JS()
|
@JS()
|
||||||
external double method();
|
external double method();
|
||||||
}
|
}
|
||||||
|
|
|
@ -163,8 +163,8 @@ class _JSLowerer extends Transformer {
|
||||||
.getClass('dart:_js_helper', 'JSValue')
|
.getClass('dart:_js_helper', 'JSValue')
|
||||||
.procedures
|
.procedures
|
||||||
.firstWhere((p) => p.name.text == 'unbox'),
|
.firstWhere((p) => p.name.text == 'unbox'),
|
||||||
_allowInteropTarget =
|
_allowInteropTarget = _coreTypes.index
|
||||||
_coreTypes.index.getTopLevelProcedure('dart:js', 'allowInterop'),
|
.getTopLevelProcedure('dart:js_util', 'allowInterop'),
|
||||||
_inlineJSTarget =
|
_inlineJSTarget =
|
||||||
_coreTypes.index.getTopLevelProcedure('dart:_js_helper', 'JS'),
|
_coreTypes.index.getTopLevelProcedure('dart:_js_helper', 'JS'),
|
||||||
_wasmExternRefClass =
|
_wasmExternRefClass =
|
||||||
|
|
|
@ -61,7 +61,6 @@ class WasmTarget extends Target {
|
||||||
'dart:typed_data',
|
'dart:typed_data',
|
||||||
'dart:nativewrappers',
|
'dart:nativewrappers',
|
||||||
'dart:io',
|
'dart:io',
|
||||||
'dart:js',
|
|
||||||
'dart:js_util',
|
'dart:js_util',
|
||||||
'dart:wasm',
|
'dart:wasm',
|
||||||
'dart:developer',
|
'dart:developer',
|
||||||
|
@ -73,7 +72,6 @@ class WasmTarget extends Target {
|
||||||
'dart:_js_interop',
|
'dart:_js_interop',
|
||||||
'dart:collection',
|
'dart:collection',
|
||||||
'dart:typed_data',
|
'dart:typed_data',
|
||||||
'dart:js',
|
|
||||||
'dart:js_util',
|
'dart:js_util',
|
||||||
'dart:wasm',
|
'dart:wasm',
|
||||||
];
|
];
|
||||||
|
|
|
@ -34,7 +34,7 @@ bool _isJSLibrary(Library library) => _isLibrary(library, [
|
||||||
bool isAllowInterop(Expression node) {
|
bool isAllowInterop(Expression node) {
|
||||||
if (node is StaticInvocation) {
|
if (node is StaticInvocation) {
|
||||||
var target = node.target;
|
var target = node.target;
|
||||||
return _isLibrary(target.enclosingLibrary, ['dart:js']) &&
|
return _isLibrary(target.enclosingLibrary, ['dart:js_util']) &&
|
||||||
target.name.text == 'allowInterop';
|
target.name.text == 'allowInterop';
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -7,7 +7,7 @@ library js;
|
||||||
|
|
||||||
import 'package:meta/meta.dart';
|
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
|
/// An annotation that indicates a library, class, or member is implemented
|
||||||
/// directly in JavaScript.
|
/// directly in JavaScript.
|
||||||
|
|
|
@ -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<Function> _interopExpando = Expando<Function>();
|
||||||
|
|
||||||
|
@patch
|
||||||
|
F allowInterop<F extends Function>(F f) {
|
||||||
|
if (!dart.isDartFunction(f)) return f;
|
||||||
|
var ret = _interopExpando[f] as F?;
|
||||||
|
if (ret == null) {
|
||||||
|
ret = JS<F>(
|
||||||
|
'',
|
||||||
|
'function (...args) {'
|
||||||
|
' return #(#, args);'
|
||||||
|
'}',
|
||||||
|
dart.dcall,
|
||||||
|
f);
|
||||||
|
_interopExpando[f] = ret;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
Expando<Function> _interopCaptureThisExpando = Expando<Function>();
|
||||||
|
|
||||||
|
@patch
|
||||||
|
Function allowInteropCaptureThis(Function f) {
|
||||||
|
if (!dart.isDartFunction(f)) return f;
|
||||||
|
var ret = _interopCaptureThisExpando[f];
|
||||||
|
if (ret == null) {
|
||||||
|
ret = JS<Function>(
|
||||||
|
'',
|
||||||
|
'function(...arguments) {'
|
||||||
|
' let args = [this];'
|
||||||
|
' args.push.apply(args, arguments);'
|
||||||
|
' return #(#, args);'
|
||||||
|
'}',
|
||||||
|
dart.dcall,
|
||||||
|
f);
|
||||||
|
_interopCaptureThisExpando[f] = ret;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
|
@ -404,43 +404,3 @@ T _putIfAbsent<T>(Object weakMap, Object o, T getValue(Object o)) {
|
||||||
// TODO(vsm): Static cast. Unnecessary?
|
// TODO(vsm): Static cast. Unnecessary?
|
||||||
return JS('', '#', value);
|
return JS('', '#', value);
|
||||||
}
|
}
|
||||||
|
|
||||||
Expando<Function> _interopExpando = Expando<Function>();
|
|
||||||
|
|
||||||
@patch
|
|
||||||
F allowInterop<F extends Function>(F f) {
|
|
||||||
if (!dart.isDartFunction(f)) return f;
|
|
||||||
var ret = _interopExpando[f] as F?;
|
|
||||||
if (ret == null) {
|
|
||||||
ret = JS<F>(
|
|
||||||
'',
|
|
||||||
'function (...args) {'
|
|
||||||
' return #(#, args);'
|
|
||||||
'}',
|
|
||||||
dart.dcall,
|
|
||||||
f);
|
|
||||||
_interopExpando[f] = ret;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
Expando<Function> _interopCaptureThisExpando = Expando<Function>();
|
|
||||||
|
|
||||||
@patch
|
|
||||||
Function allowInteropCaptureThis(Function f) {
|
|
||||||
if (!dart.isDartFunction(f)) return f;
|
|
||||||
var ret = _interopCaptureThisExpando[f];
|
|
||||||
if (ret == null) {
|
|
||||||
ret = JS<Function>(
|
|
||||||
'',
|
|
||||||
'function(...arguments) {'
|
|
||||||
' let args = [this];'
|
|
||||||
' args.push.apply(args, arguments);'
|
|
||||||
' return #(#, args);'
|
|
||||||
'}',
|
|
||||||
dart.dcall,
|
|
||||||
f);
|
|
||||||
_interopCaptureThisExpando[f] = ret;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
82
sdk/lib/_internal/js_runtime/lib/js_allow_interop_patch.dart
Normal file
82
sdk/lib/_internal/js_runtime/lib/js_allow_interop_patch.dart
Normal file
|
@ -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 extends Function>(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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -82,6 +82,9 @@ part 'string_helper.dart';
|
||||||
part 'linked_hash_map.dart';
|
part 'linked_hash_map.dart';
|
||||||
part 'records.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
|
/// Marks the internal map in dart2js, so that internal libraries can is-check
|
||||||
/// them.
|
/// them.
|
||||||
abstract class InternalMap {}
|
abstract class InternalMap {}
|
||||||
|
|
|
@ -9,7 +9,12 @@ import 'dart:typed_data' show TypedData;
|
||||||
import 'dart:_foreign_helper' show JS, DART_CLOSURE_TO_JS;
|
import 'dart:_foreign_helper' show JS, DART_CLOSURE_TO_JS;
|
||||||
import 'dart:_interceptors' show DART_CLOSURE_PROPERTY_NAME;
|
import 'dart:_interceptors' show DART_CLOSURE_PROPERTY_NAME;
|
||||||
import 'dart:_internal' show patch;
|
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;
|
import 'dart:_js' show isBrowserObject, convertFromBrowserObject;
|
||||||
|
|
||||||
@patch
|
@patch
|
||||||
|
@ -370,8 +375,6 @@ final String _DART_OBJECT_PROPERTY_NAME =
|
||||||
|
|
||||||
// property added to a JS object referencing its Dart-side JsObject proxy
|
// property added to a JS object referencing its Dart-side JsObject proxy
|
||||||
const _JS_OBJECT_PROPERTY_NAME = r'_$dart_jsObject';
|
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')
|
@pragma('dart2js:tryInline')
|
||||||
JsObject _castToJsObject(o) => JS<JsObject>('', '#', o);
|
JsObject _castToJsObject(o) => JS<JsObject>('', '#', o);
|
||||||
|
@ -431,7 +434,7 @@ Object? _convertToJS(Object? o) {
|
||||||
return Primitives.lazyAsJsDate(o);
|
return Primitives.lazyAsJsDate(o);
|
||||||
}
|
}
|
||||||
if (o is Function) {
|
if (o is Function) {
|
||||||
return _getJsProxy(o, _JS_FUNCTION_PROPERTY_NAME, (o) {
|
return _getJsProxy(o, JS_FUNCTION_PROPERTY_NAME, (o) {
|
||||||
var jsFunction = _convertDartFunction(o);
|
var jsFunction = _convertDartFunction(o);
|
||||||
// set a property on the JS closure referencing the Dart closure
|
// set a property on the JS closure referencing the Dart closure
|
||||||
_defineProperty(jsFunction, DART_CLOSURE_PROPERTY_NAME, o);
|
_defineProperty(jsFunction, DART_CLOSURE_PROPERTY_NAME, o);
|
||||||
|
@ -502,71 +505,3 @@ Object _getDartProxy(o, String propertyName, JsObject createProxy(o)) {
|
||||||
}
|
}
|
||||||
return dartProxy;
|
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 extends Function>(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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -8,7 +8,6 @@ import 'dart:_js_helper'
|
||||||
show convertDartClosureToJS, assertInterop, assertInteropArgs;
|
show convertDartClosureToJS, assertInterop, assertInteropArgs;
|
||||||
import 'dart:collection' show HashMap;
|
import 'dart:collection' show HashMap;
|
||||||
import 'dart:async' show Completer;
|
import 'dart:async' show Completer;
|
||||||
import 'dart:js_util';
|
|
||||||
|
|
||||||
@patch
|
@patch
|
||||||
dynamic jsify(Object object) {
|
dynamic jsify(Object object) {
|
||||||
|
|
|
@ -113,10 +113,3 @@ class JsArray<E> extends JsObject with ListMixin<E> {
|
||||||
@patch
|
@patch
|
||||||
void sort([int compare(E a, E b)?]) => throw UnimplementedError();
|
void sort([int compare(E a, E b)?]) => throw UnimplementedError();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This will be lowered to a call to `_wrapDartCallback`.
|
|
||||||
@patch
|
|
||||||
F allowInterop<F extends Function>(F f) => throw UnimplementedError();
|
|
||||||
|
|
||||||
@patch
|
|
||||||
Function allowInteropCaptureThis(Function f) => throw UnimplementedError();
|
|
||||||
|
|
|
@ -150,10 +150,10 @@ typedef _PromiseFailureFunc = void Function(Object? error);
|
||||||
Future<T> promiseToFuture<T>(Object jsPromise) {
|
Future<T> promiseToFuture<T>(Object jsPromise) {
|
||||||
Completer<T> completer = Completer<T>();
|
Completer<T> completer = Completer<T>();
|
||||||
|
|
||||||
final success = js.allowInterop<_PromiseSuccessFunc>((r) {
|
final success = allowInterop<_PromiseSuccessFunc>((r) {
|
||||||
return completer.complete(r as FutureOr<T>?);
|
return completer.complete(r as FutureOr<T>?);
|
||||||
});
|
});
|
||||||
final error = js.allowInterop<_PromiseFailureFunc>((e) {
|
final error = allowInterop<_PromiseFailureFunc>((e) {
|
||||||
// Note that `completeError` expects a non-nullable error regardless of
|
// Note that `completeError` expects a non-nullable error regardless of
|
||||||
// whether null-safety is enabled, so a `NullRejectionException` is always
|
// whether null-safety is enabled, so a `NullRejectionException` is always
|
||||||
// provided if the error is `null` or `undefined`.
|
// provided if the error is `null` or `undefined`.
|
||||||
|
@ -257,3 +257,10 @@ Object? dartify(Object? object) {
|
||||||
|
|
||||||
return convert(object);
|
return convert(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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();
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
// https://github.com/dart-lang/sdk/blob/master/pkg/js/lib/js.dart
|
// https://github.com/dart-lang/sdk/blob/master/pkg/js/lib/js.dart
|
||||||
library _js_annotations;
|
library _js_annotations;
|
||||||
|
|
||||||
export 'dart:js' show allowInterop, allowInteropCaptureThis;
|
export 'dart:js_util' show allowInterop, allowInteropCaptureThis;
|
||||||
|
|
||||||
class JS {
|
class JS {
|
||||||
final String? name;
|
final String? name;
|
||||||
|
|
|
@ -86,6 +86,8 @@ library dart.js;
|
||||||
|
|
||||||
import 'dart:collection' show ListMixin;
|
import 'dart:collection' show ListMixin;
|
||||||
|
|
||||||
|
export 'dart:js_util' show allowInterop, allowInteropCaptureThis;
|
||||||
|
|
||||||
/// The JavaScript global object, usually `window`.
|
/// The JavaScript global object, usually `window`.
|
||||||
external JsObject get context;
|
external JsObject get context;
|
||||||
|
|
||||||
|
@ -209,25 +211,3 @@ class JsArray<E> extends JsObject with ListMixin<E> {
|
||||||
|
|
||||||
external void sort([int compare(E a, E b)?]);
|
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 extends Function>(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);
|
|
||||||
|
|
|
@ -256,3 +256,25 @@ external T createStaticInteropMock<T extends Object, U extends Object>(
|
||||||
/// Expect.isTrue(counter.stringify(), export.stringify());
|
/// Expect.isTrue(counter.stringify(), export.stringify());
|
||||||
/// ```
|
/// ```
|
||||||
external Object createDartExport<T extends Object>(T dartObject);
|
external Object createDartExport<T extends Object>(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 extends Function>(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);
|
||||||
|
|
|
@ -334,7 +334,10 @@
|
||||||
},
|
},
|
||||||
"js_util": {
|
"js_util": {
|
||||||
"uri": "js_util/js_util.dart",
|
"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": {
|
"math": {
|
||||||
"uri": "math/math.dart",
|
"uri": "math/math.dart",
|
||||||
|
@ -506,7 +509,10 @@
|
||||||
},
|
},
|
||||||
"js_util": {
|
"js_util": {
|
||||||
"uri": "js_util/js_util.dart",
|
"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": {
|
"svg": {
|
||||||
"uri": "svg/dart2js/svg_dart2js.dart"
|
"uri": "svg/dart2js/svg_dart2js.dart"
|
||||||
|
|
|
@ -287,7 +287,9 @@ _dart2js_common:
|
||||||
|
|
||||||
js_util:
|
js_util:
|
||||||
uri: "js_util/js_util.dart"
|
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:
|
math:
|
||||||
uri: "math/math.dart"
|
uri: "math/math.dart"
|
||||||
|
@ -457,7 +459,9 @@ dartdevc:
|
||||||
|
|
||||||
js_util:
|
js_util:
|
||||||
uri: "js_util/js_util.dart"
|
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:
|
svg:
|
||||||
uri: "svg/dart2js/svg_dart2js.dart"
|
uri: "svg/dart2js/svg_dart2js.dart"
|
||||||
|
|
Loading…
Reference in a new issue