mirror of
https://github.com/dart-lang/sdk
synced 2024-07-01 07:14:29 +00:00
[dart2wasm/ddc/dart2js] Lower Function.toJS and JSExportedDartFunction.toDart
Lowers these extension methods to some helper functions instead of allowInterop to improve performance and get consistent semantics. Specifically: - Function.toJS no longer gives you the same JSFunction when calling toJS on the same function multiple times in the JS compilers. - Adds fast calling syntax for functions with 0-5 args in the JS compilers. - Allows additional args to be passed to converted functions that are omitted in the JS compilers. - The static type now determines the number of args that can be passed to the JS function in the JS compilers. - Fixes an issue in dart2wasm where if too few arguments are passed, the call may succeed due to conversion of undefined to null. - Adds throws when a user tries to wrap a JS function that returned from Function.toJS in the JS compilers. Closes https://github.com/dart-lang/sdk/issues/55515 Addresses https://github.com/dart-lang/sdk/issues/48186 CoreLibraryReviewExempt: Changes to docs only in API surface. Change-Id: I41d864dc5e02b597d9f1c16c88e3c04872f28225 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/368065 Reviewed-by: Nicholas Shahan <nshahan@google.com> Reviewed-by: Stephen Adams <sra@google.com> Commit-Queue: Srujan Gaddam <srujzs@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com>
This commit is contained in:
parent
4b88698e48
commit
1c534e5fd5
|
@ -64,11 +64,19 @@
|
|||
`ExternalDartReferenceToObject` and `ObjectToExternalDartReference` are now
|
||||
extensions on `T` and `ExternalDartReference<T>`, respectively, where `T
|
||||
extends Object?`. See [#55342][] and [#55536][] for more details.
|
||||
- Fixes some consistency issues with `Function.toJS` across all compilers.
|
||||
Specifically, calling `Function.toJS` on the same function gives you a new JS
|
||||
function (see issue [#55515][]), the max number of args that are passed to the
|
||||
JS function is determined by the static type of the Dart function, and extra
|
||||
args are dropped when passed to the JS function in all compilers (see
|
||||
[#48186][]).
|
||||
|
||||
[#55508]: https://github.com/dart-lang/sdk/issues/55508
|
||||
[#55267]: https://github.com/dart-lang/sdk/issues/55267
|
||||
[#55342]: https://github.com/dart-lang/sdk/issues/55342
|
||||
[#55536]: https://github.com/dart-lang/sdk/issues/55536
|
||||
[#55515]: https://github.com/dart-lang/sdk/issues/55515
|
||||
[#48186]: https://github.com/dart-lang/sdk/issues/48186
|
||||
|
||||
### Tools
|
||||
|
||||
|
|
|
@ -41,9 +41,14 @@ class JsUtilOptimizer extends Transformer {
|
|||
final List<Procedure> _callConstructorUncheckedTargets;
|
||||
final CloneVisitorNotMembers _cloner = CloneVisitorWithMembers();
|
||||
final Map<Member, _InvocationBuilder?> _externalInvocationBuilders = {};
|
||||
final Procedure _functionToJSTarget;
|
||||
final List<Procedure> _functionToJSTargets;
|
||||
final Procedure _functionToJSNTarget;
|
||||
final Procedure _getPropertyTarget;
|
||||
final Procedure _getPropertyTrustTypeTarget;
|
||||
final Procedure _globalContextTarget;
|
||||
final Procedure _jsExportedDartFunctionToDartTarget;
|
||||
final Procedure _jsFunctionToDart;
|
||||
final InterfaceType _objectType;
|
||||
final Procedure _setPropertyTarget;
|
||||
final Procedure _setPropertyUncheckedTarget;
|
||||
|
@ -88,12 +93,25 @@ class JsUtilOptimizer extends Transformer {
|
|||
5,
|
||||
(i) => _coreTypes.index.getTopLevelProcedure(
|
||||
'dart:js_util', '_callConstructorUnchecked$i')),
|
||||
_functionToJSTarget = _coreTypes.index.getTopLevelProcedure(
|
||||
'dart:js_interop', 'FunctionToJSExportedDartFunction|get#toJS'),
|
||||
_functionToJSTargets = List<Procedure>.generate(
|
||||
6,
|
||||
(i) => _coreTypes.index
|
||||
.getTopLevelProcedure('dart:js_util', '_functionToJS$i')),
|
||||
_functionToJSNTarget = _coreTypes.index
|
||||
.getTopLevelProcedure('dart:js_util', '_functionToJSN'),
|
||||
_getPropertyTarget = _coreTypes.index
|
||||
.getTopLevelProcedure('dart:js_util', 'getProperty'),
|
||||
_getPropertyTrustTypeTarget = _coreTypes.index
|
||||
.getTopLevelProcedure('dart:js_util', '_getPropertyTrustType'),
|
||||
_globalContextTarget = _coreTypes.index.getTopLevelProcedure(
|
||||
'dart:_js_helper', 'get:staticInteropGlobalContext'),
|
||||
_jsExportedDartFunctionToDartTarget = _coreTypes.index
|
||||
.getTopLevelProcedure('dart:js_interop',
|
||||
'JSExportedDartFunctionToFunction|get#toDart'),
|
||||
_jsFunctionToDart = _coreTypes.index
|
||||
.getTopLevelProcedure('dart:js_util', '_jsFunctionToDart'),
|
||||
_objectType = hierarchy.coreTypes.objectNonNullableRawType,
|
||||
_setPropertyTarget = _coreTypes.index
|
||||
.getTopLevelProcedure('dart:js_util', 'setProperty'),
|
||||
|
@ -480,6 +498,10 @@ class JsUtilOptimizer extends Transformer {
|
|||
invocation = _lowerCallConstructor(node);
|
||||
// TODO(srujzs): Delete the `isPatchedMember` check once
|
||||
// https://github.com/dart-lang/sdk/issues/53367 is resolved.
|
||||
} else if (target == _functionToJSTarget) {
|
||||
invocation = _lowerFunctionToJS(node);
|
||||
} else if (target == _jsExportedDartFunctionToDartTarget) {
|
||||
invocation = _lowerJSExportedDartFunctionToDart(node);
|
||||
} else if (target.isExternal && !JsInteropChecks.isPatchedMember(target)) {
|
||||
final builder = _externalInvocationBuilders.putIfAbsent(
|
||||
target, () => _getExternalInvocationBuilder(target));
|
||||
|
@ -662,6 +684,45 @@ class JsUtilOptimizer extends Transformer {
|
|||
..parent = nodeParent;
|
||||
}
|
||||
|
||||
/// For the given `dart:js_interop` `Function.toJS` invocation [node], returns
|
||||
/// an invocation of `_functionToJSX` with the given `Function` argument,
|
||||
/// where X is the number of the positional arguments.
|
||||
///
|
||||
/// If the number of the positional arguments is larger than 5, returns an
|
||||
/// invocation of `_functionToJSN` instead.
|
||||
StaticInvocation _lowerFunctionToJS(StaticInvocation node) {
|
||||
// JS interop checks assert that the static type is available, and that
|
||||
// there are no named arguments or type arguments.
|
||||
final function = node.arguments.positional.single;
|
||||
final functionType =
|
||||
function.getStaticType(_staticTypeContext) as FunctionType;
|
||||
final argumentsLength = functionType.positionalParameters.length;
|
||||
Procedure target;
|
||||
Arguments arguments;
|
||||
if (argumentsLength < _functionToJSTargets.length) {
|
||||
target = _functionToJSTargets[argumentsLength];
|
||||
arguments = Arguments([function]);
|
||||
} else {
|
||||
target = _functionToJSNTarget;
|
||||
arguments = Arguments([function, IntLiteral(argumentsLength)]);
|
||||
}
|
||||
return StaticInvocation(
|
||||
target, arguments..fileOffset = node.arguments.fileOffset)
|
||||
..fileOffset = node.fileOffset
|
||||
..parent = node.parent;
|
||||
}
|
||||
|
||||
/// For the given `dart:js_interop` `JSExportedDartFunction.toDart` invocation
|
||||
/// [node], returns an invocation of `_jsFunctionToDart` with the given
|
||||
/// `JSExportedDartFunction` argument.
|
||||
StaticInvocation _lowerJSExportedDartFunctionToDart(StaticInvocation node) =>
|
||||
StaticInvocation(
|
||||
_jsFunctionToDart,
|
||||
Arguments([node.arguments.positional[0]])
|
||||
..fileOffset = node.arguments.fileOffset)
|
||||
..fileOffset = node.fileOffset
|
||||
..parent = node.parent;
|
||||
|
||||
/// Returns whether the given [node] is guaranteed to be allowed to interop
|
||||
/// with JS.
|
||||
///
|
||||
|
|
|
@ -17,9 +17,6 @@ class CallbackSpecializer {
|
|||
CallbackSpecializer(
|
||||
this._staticTypeContext, this._util, this._methodCollector);
|
||||
|
||||
bool _needsArgumentsLength(FunctionType type) =>
|
||||
type.requiredParameterCount < type.positionalParameters.length;
|
||||
|
||||
Statement _generateDispatchCase(
|
||||
FunctionType function,
|
||||
VariableDeclaration callbackVariable,
|
||||
|
@ -54,12 +51,11 @@ class CallbackSpecializer {
|
|||
/// Creates a callback trampoline for the given [function].
|
||||
///
|
||||
/// This callback trampoline expects a Dart callback as its first argument,
|
||||
/// then an integer value(double type) indicating the position of the last
|
||||
/// defined argument(only for callbacks that take optional parameters),
|
||||
/// followed by all of the arguments to the Dart callback as JS objects. The
|
||||
/// trampoline will `dartifyRaw` or box all incoming JS objects and then cast
|
||||
/// them to their appropriate types, dispatch, and then `jsifyRaw` or box any
|
||||
/// returned value.
|
||||
/// then an integer value(double type) indicating the number of arguments
|
||||
/// passed, followed by all of the arguments to the Dart callback as JS
|
||||
/// objects. The trampoline will `dartifyRaw` or box all incoming JS objects
|
||||
/// and then cast them to their appropriate types, dispatch, and then
|
||||
/// `jsifyRaw` or box any returned value.
|
||||
///
|
||||
/// Returns a [String] function name representing the name of the wrapping
|
||||
/// function.
|
||||
|
@ -69,20 +65,18 @@ class CallbackSpecializer {
|
|||
// arguments will be JS objects. The generated wrapper will cast each
|
||||
// argument to the correct type. The first argument to this function will
|
||||
// be the Dart callback, which will be cast to the supplied [FunctionType]
|
||||
// before being invoked. If the callback takes optional parameters then, the
|
||||
// second argument will be a `double` indicating the last defined argument.
|
||||
// before being invoked. The second argument will be a `double` indicating
|
||||
// the number of arguments passed.
|
||||
int parameterId = 1;
|
||||
final callbackVariable = VariableDeclaration('callback',
|
||||
type: _util.nonNullableObjectType, isSynthesized: true);
|
||||
VariableDeclaration? argumentsLength;
|
||||
if (_needsArgumentsLength(function)) {
|
||||
argumentsLength = VariableDeclaration('argumentsLength',
|
||||
type: _util.coreTypes.doubleNonNullableRawType, isSynthesized: true);
|
||||
}
|
||||
final argumentsLength = VariableDeclaration('argumentsLength',
|
||||
type: _util.coreTypes.doubleNonNullableRawType, isSynthesized: true);
|
||||
|
||||
// Initialize variable declarations.
|
||||
List<VariableDeclaration> positionalParameters = [];
|
||||
for (int j = 0; j < function.positionalParameters.length; j++) {
|
||||
final positionalParametersLength = function.positionalParameters.length;
|
||||
for (int j = 0; j < positionalParametersLength; j++) {
|
||||
positionalParameters.add(VariableDeclaration('x${parameterId++}',
|
||||
type: _util.nullableWasmExternRefType, isSynthesized: true));
|
||||
}
|
||||
|
@ -91,26 +85,42 @@ class CallbackSpecializer {
|
|||
// find the last defined argument in JS, that is the last argument which was
|
||||
// explicitly passed by the user, and then we dispatch to a Dart function
|
||||
// with the right number of arguments.
|
||||
//
|
||||
// First we handle cases where some or all arguments are undefined.
|
||||
// TODO(joshualitt): Consider using a switch instead.
|
||||
List<Statement> dispatchCases = [];
|
||||
for (int i = function.requiredParameterCount + 1;
|
||||
i <= function.positionalParameters.length;
|
||||
i++) {
|
||||
// If more arguments were passed than there are parameters, ignore the extra
|
||||
// arguments.
|
||||
dispatchCases.add(IfStatement(
|
||||
_util.variableGreaterThanOrEqualToConstant(
|
||||
argumentsLength, IntConstant(positionalParametersLength)),
|
||||
_generateDispatchCase(function, callbackVariable, positionalParameters,
|
||||
positionalParametersLength,
|
||||
boxExternRef: boxExternRef),
|
||||
null));
|
||||
// TODO(srujzs): Consider using a switch instead.
|
||||
for (int i = positionalParametersLength - 1;
|
||||
i >= function.requiredParameterCount;
|
||||
i--) {
|
||||
dispatchCases.add(IfStatement(
|
||||
_util.variableCheckConstant(
|
||||
argumentsLength!, DoubleConstant(i.toDouble())),
|
||||
argumentsLength, DoubleConstant(i.toDouble())),
|
||||
_generateDispatchCase(
|
||||
function, callbackVariable, positionalParameters, i,
|
||||
boxExternRef: boxExternRef),
|
||||
null));
|
||||
}
|
||||
|
||||
// Finally handle the case where only required parameters are passed.
|
||||
dispatchCases.add(_generateDispatchCase(function, callbackVariable,
|
||||
positionalParameters, function.requiredParameterCount,
|
||||
boxExternRef: boxExternRef));
|
||||
// Throw since we have too few arguments. Alternatively, we can continue
|
||||
// checking lengths and try to call the callback, which will then throw, but
|
||||
// that's unnecessary extra code. Note that we can't exclude this and assume
|
||||
// the last dispatch case will catch this. Since arguments that are not
|
||||
// passed are `undefined` and `undefined` gets converted to `null`, they may
|
||||
// be treated as valid `null` arguments to the Dart function even though
|
||||
// they were never passed.
|
||||
dispatchCases.add(ExpressionStatement(Throw(StringConcatenation([
|
||||
StringLiteral('Too few arguments passed. '
|
||||
'Expected ${function.requiredParameterCount} or more, got '),
|
||||
invokeMethod(argumentsLength, _util.numToIntTarget),
|
||||
StringLiteral(' instead.')
|
||||
]))));
|
||||
Statement functionTrampolineBody = Block(dispatchCases);
|
||||
|
||||
// Create a new procedure for the callback trampoline. This procedure will
|
||||
|
@ -124,8 +134,9 @@ class CallbackSpecializer {
|
|||
FunctionNode(functionTrampolineBody,
|
||||
positionalParameters: [
|
||||
callbackVariable,
|
||||
if (argumentsLength != null) argumentsLength
|
||||
].followedBy(positionalParameters).toList(),
|
||||
argumentsLength,
|
||||
...positionalParameters
|
||||
],
|
||||
returnType: _util.nullableWasmExternRefType)
|
||||
..fileOffset = node.fileOffset,
|
||||
node.fileUri,
|
||||
|
@ -144,11 +155,7 @@ class CallbackSpecializer {
|
|||
jsParameters.add('x$i');
|
||||
}
|
||||
String jsParametersString = jsParameters.join(',');
|
||||
String dartArguments = 'f';
|
||||
bool needsArguments = _needsArgumentsLength(type);
|
||||
if (needsArguments) {
|
||||
dartArguments = '$dartArguments,arguments.length';
|
||||
}
|
||||
String dartArguments = 'f,arguments.length';
|
||||
if (jsParameters.isNotEmpty) {
|
||||
dartArguments = '$dartArguments,$jsParametersString';
|
||||
}
|
||||
|
@ -171,24 +178,12 @@ class CallbackSpecializer {
|
|||
// Create JS method.
|
||||
// Note: We have to use a regular function for the inner closure in some
|
||||
// cases because we need access to `arguments`.
|
||||
if (needsArguments) {
|
||||
_methodCollector.addMethod(
|
||||
dartProcedure,
|
||||
jsMethodName,
|
||||
"f => finalizeWrapper(f, function($jsParametersString) {"
|
||||
" return dartInstance.exports.$functionTrampolineName($dartArguments) "
|
||||
"})");
|
||||
} else {
|
||||
if (parametersNeedParens(jsParameters)) {
|
||||
jsParametersString = '($jsParametersString)';
|
||||
}
|
||||
_methodCollector.addMethod(
|
||||
dartProcedure,
|
||||
jsMethodName,
|
||||
"f => "
|
||||
"finalizeWrapper(f,$jsParametersString => "
|
||||
"dartInstance.exports.$functionTrampolineName($dartArguments))");
|
||||
}
|
||||
_methodCollector.addMethod(
|
||||
dartProcedure,
|
||||
jsMethodName,
|
||||
"f => finalizeWrapper(f, function($jsParametersString) {"
|
||||
" return dartInstance.exports.$functionTrampolineName($dartArguments) "
|
||||
"})");
|
||||
|
||||
return dartProcedure;
|
||||
}
|
||||
|
@ -207,6 +202,9 @@ class CallbackSpecializer {
|
|||
/// these Dart functions flow to JS, they are replaced by their wrappers. If
|
||||
/// the wrapper should ever flow back into Dart then it will be replaced by
|
||||
/// the original Dart function.
|
||||
// TODO(srujzs): It looks like there's no more code that references this
|
||||
// function anymore in dart2wasm. Should we delete this lowering and related
|
||||
// code?
|
||||
Expression allowInterop(StaticInvocation staticInvocation) {
|
||||
final argument = staticInvocation.arguments.positional.single;
|
||||
final type = argument.getStaticType(_staticTypeContext) as FunctionType;
|
||||
|
|
|
@ -16,6 +16,7 @@ class CoreTypesUtil {
|
|||
final Procedure allowInteropTarget;
|
||||
final Procedure dartifyRawTarget;
|
||||
final Procedure functionToJSTarget;
|
||||
final Procedure greaterThanOrEqualToTarget;
|
||||
final Procedure inlineJSTarget;
|
||||
final Procedure isDartFunctionWrappedTarget;
|
||||
final Procedure jsifyRawTarget;
|
||||
|
@ -33,6 +34,8 @@ class CoreTypesUtil {
|
|||
.getTopLevelProcedure('dart:_js_helper', 'dartifyRaw'),
|
||||
functionToJSTarget = coreTypes.index.getTopLevelProcedure(
|
||||
'dart:js_interop', 'FunctionToJSExportedDartFunction|get#toJS'),
|
||||
greaterThanOrEqualToTarget =
|
||||
coreTypes.index.getProcedure('dart:core', 'num', '>='),
|
||||
inlineJSTarget =
|
||||
coreTypes.index.getTopLevelProcedure('dart:_js_helper', 'JS'),
|
||||
isDartFunctionWrappedTarget = coreTypes.index
|
||||
|
@ -94,6 +97,17 @@ class CoreTypesUtil {
|
|||
StaticInvocation(coreTypes.identicalProcedure,
|
||||
Arguments([VariableGet(variable), ConstantExpression(constant)]));
|
||||
|
||||
Expression variableGreaterThanOrEqualToConstant(
|
||||
VariableDeclaration variable, Constant constant) =>
|
||||
InstanceInvocation(
|
||||
InstanceAccessKind.Instance,
|
||||
VariableGet(variable),
|
||||
greaterThanOrEqualToTarget.name,
|
||||
Arguments([ConstantExpression(constant)]),
|
||||
interfaceTarget: greaterThanOrEqualToTarget,
|
||||
functionType: greaterThanOrEqualToTarget.getterType as FunctionType,
|
||||
);
|
||||
|
||||
/// Cast the [invocation] if needed to conform to the expected [returnType].
|
||||
Expression castInvocationForReturn(
|
||||
Expression invocation, DartType returnType) {
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
library;
|
||||
import self as self;
|
||||
import "dart:js_interop" as js_;
|
||||
import "dart:js_util" as js_;
|
||||
import "dart:core" as core;
|
||||
|
||||
import "dart:js_interop";
|
||||
|
||||
static method main() → void {
|
||||
js_::JSExportedDartFunction /* erasure=_interceptors::JavaScriptFunction */ jsFunction = js_::FunctionToJSExportedDartFunction|get#toJS(() → Null {});
|
||||
js_::FunctionToJSExportedDartFunction|get#toJS((core::int arg1) → core::int => arg1);
|
||||
js_::FunctionToJSExportedDartFunction|get#toJS((([core::int? arg1 = #C1]) → core::int? => arg1) as () → void);
|
||||
js_::FunctionToJSExportedDartFunction|get#toJS((core::int arg1, core::String arg2) → core::String => arg2);
|
||||
js_::FunctionToJSExportedDartFunction|get#toJS((([core::int? arg1 = #C1, core::String? arg2 = #C1]) → core::String? => arg2) as ([core::int]) → void);
|
||||
js_::FunctionToJSExportedDartFunction|get#toJS((core::int arg1, core::String arg2, js_::JSArray<js_::JSAny? /* erasure=core::Object? */> /* erasure=_interceptors::JSArray<core::Object?> */ arg3) → js_::JSArray<js_::JSAny? /* erasure=core::Object? */> /* erasure=_interceptors::JSArray<core::Object?> */ => arg3);
|
||||
js_::FunctionToJSExportedDartFunction|get#toJS(((core::int arg1, [core::String? arg2 = #C1, js_::JSArray<js_::JSAny? /* erasure=core::Object? */>? /* erasure=_interceptors::JSArray<core::Object?>? */ arg3 = #C1]) → js_::JSArray<js_::JSAny? /* erasure=core::Object? */>? /* erasure=_interceptors::JSArray<core::Object?>? */ => arg3) as (core::int, [core::String]) → void);
|
||||
js_::FunctionToJSExportedDartFunction|get#toJS((core::int arg1, core::String arg2, js_::JSArray<js_::JSAny? /* erasure=core::Object? */> /* erasure=_interceptors::JSArray<core::Object?> */ arg3, js_::JSObject /* erasure=_interceptors::JSObject */ arg4) → js_::JSObject /* erasure=_interceptors::JSObject */ => arg4);
|
||||
js_::FunctionToJSExportedDartFunction|get#toJS(((core::int arg1, core::String arg2, js_::JSArray<js_::JSAny? /* erasure=core::Object? */> /* erasure=_interceptors::JSArray<core::Object?> */ arg3, [js_::JSObject? /* erasure=_interceptors::JSObject? */ arg4 = #C1]) → js_::JSObject? /* erasure=_interceptors::JSObject? */ => arg4) as (core::int, core::String, js_::JSArray<js_::JSAny? /* erasure=core::Object? */> /* erasure=_interceptors::JSArray<core::Object?> */) → void);
|
||||
js_::FunctionToJSExportedDartFunction|get#toJS((core::int arg1, core::String arg2, js_::JSArray<js_::JSAny? /* erasure=core::Object? */> /* erasure=_interceptors::JSArray<core::Object?> */ arg3, js_::JSObject /* erasure=_interceptors::JSObject */ arg4, js_::JSPromise<js_::JSAny? /* erasure=core::Object? */> /* erasure=_interceptors::JSObject */ arg5) → js_::JSPromise<js_::JSAny? /* erasure=core::Object? */> /* erasure=_interceptors::JSObject */ => arg5);
|
||||
js_::FunctionToJSExportedDartFunction|get#toJS(((core::int arg1, core::String arg2, [js_::JSArray<js_::JSAny? /* erasure=core::Object? */>? /* erasure=_interceptors::JSArray<core::Object?>? */ arg3 = #C1, js_::JSObject? /* erasure=_interceptors::JSObject? */ arg4 = #C1, js_::JSPromise<js_::JSAny? /* erasure=core::Object? */>? /* erasure=_interceptors::JSObject? */ arg5 = #C1]) → js_::JSPromise<js_::JSAny? /* erasure=core::Object? */>? /* erasure=_interceptors::JSObject? */ => arg5) as (core::int, core::String, [js_::JSArray<js_::JSAny? /* erasure=core::Object? */>? /* erasure=_interceptors::JSArray<core::Object?>? */, js_::JSObject? /* erasure=_interceptors::JSObject? */]) → void);
|
||||
js_::FunctionToJSExportedDartFunction|get#toJS((core::int arg1, core::String arg2, js_::JSArray<js_::JSAny? /* erasure=core::Object? */> /* erasure=_interceptors::JSArray<core::Object?> */ arg3, js_::JSObject /* erasure=_interceptors::JSObject */ arg4, js_::JSPromise<js_::JSAny? /* erasure=core::Object? */> /* erasure=_interceptors::JSObject */ arg5, js_::JSAny /* erasure=core::Object */ arg6) → js_::JSAny /* erasure=core::Object */ => arg6);
|
||||
js_::FunctionToJSExportedDartFunction|get#toJS(((core::int arg1, core::String arg2, js_::JSArray<js_::JSAny? /* erasure=core::Object? */> /* erasure=_interceptors::JSArray<core::Object?> */ arg3, js_::JSObject /* erasure=_interceptors::JSObject */ arg4, [js_::JSPromise<js_::JSAny? /* erasure=core::Object? */>? /* erasure=_interceptors::JSObject? */ arg5 = #C1, js_::JSAny? /* erasure=core::Object? */ arg6 = #C1]) → js_::JSAny? /* erasure=core::Object? */ => arg6) as (core::int, core::String, js_::JSArray<js_::JSAny? /* erasure=core::Object? */> /* erasure=_interceptors::JSArray<core::Object?> */, js_::JSObject /* erasure=_interceptors::JSObject */, [js_::JSPromise<js_::JSAny? /* erasure=core::Object? */>? /* erasure=_interceptors::JSObject? */]) → void);
|
||||
js_::JSExportedDartFunctionToFunction|get#toDart(jsFunction);
|
||||
#lib1::JSExportedDartFunction /* erasure=_interceptors::JavaScriptFunction */ jsFunction = js_::_functionToJS0(() → Null {});
|
||||
js_::_functionToJS1((core::int arg1) → core::int => arg1);
|
||||
js_::_functionToJS0((([core::int? arg1 = #C1]) → core::int? => arg1) as () → void);
|
||||
js_::_functionToJS2((core::int arg1, core::String arg2) → core::String => arg2);
|
||||
js_::_functionToJS1((([core::int? arg1 = #C1, core::String? arg2 = #C1]) → core::String? => arg2) as ([core::int]) → void);
|
||||
js_::_functionToJS3((core::int arg1, core::String arg2, #lib1::JSArray<#lib1::JSAny? /* erasure=core::Object? */> /* erasure=_interceptors::JSArray<core::Object?> */ arg3) → #lib1::JSArray<#lib1::JSAny? /* erasure=core::Object? */> /* erasure=_interceptors::JSArray<core::Object?> */ => arg3);
|
||||
js_::_functionToJS2(((core::int arg1, [core::String? arg2 = #C1, #lib1::JSArray<#lib1::JSAny? /* erasure=core::Object? */>? /* erasure=_interceptors::JSArray<core::Object?>? */ arg3 = #C1]) → #lib1::JSArray<#lib1::JSAny? /* erasure=core::Object? */>? /* erasure=_interceptors::JSArray<core::Object?>? */ => arg3) as (core::int, [core::String]) → void);
|
||||
js_::_functionToJS4((core::int arg1, core::String arg2, #lib1::JSArray<#lib1::JSAny? /* erasure=core::Object? */> /* erasure=_interceptors::JSArray<core::Object?> */ arg3, #lib1::JSObject /* erasure=_interceptors::JSObject */ arg4) → #lib1::JSObject /* erasure=_interceptors::JSObject */ => arg4);
|
||||
js_::_functionToJS3(((core::int arg1, core::String arg2, #lib1::JSArray<#lib1::JSAny? /* erasure=core::Object? */> /* erasure=_interceptors::JSArray<core::Object?> */ arg3, [#lib1::JSObject? /* erasure=_interceptors::JSObject? */ arg4 = #C1]) → #lib1::JSObject? /* erasure=_interceptors::JSObject? */ => arg4) as (core::int, core::String, #lib1::JSArray<#lib1::JSAny? /* erasure=core::Object? */> /* erasure=_interceptors::JSArray<core::Object?> */) → void);
|
||||
js_::_functionToJS5((core::int arg1, core::String arg2, #lib1::JSArray<#lib1::JSAny? /* erasure=core::Object? */> /* erasure=_interceptors::JSArray<core::Object?> */ arg3, #lib1::JSObject /* erasure=_interceptors::JSObject */ arg4, #lib1::JSPromise<#lib1::JSAny? /* erasure=core::Object? */> /* erasure=_interceptors::JSObject */ arg5) → #lib1::JSPromise<#lib1::JSAny? /* erasure=core::Object? */> /* erasure=_interceptors::JSObject */ => arg5);
|
||||
js_::_functionToJS4(((core::int arg1, core::String arg2, [#lib1::JSArray<#lib1::JSAny? /* erasure=core::Object? */>? /* erasure=_interceptors::JSArray<core::Object?>? */ arg3 = #C1, #lib1::JSObject? /* erasure=_interceptors::JSObject? */ arg4 = #C1, #lib1::JSPromise<#lib1::JSAny? /* erasure=core::Object? */>? /* erasure=_interceptors::JSObject? */ arg5 = #C1]) → #lib1::JSPromise<#lib1::JSAny? /* erasure=core::Object? */>? /* erasure=_interceptors::JSObject? */ => arg5) as (core::int, core::String, [#lib1::JSArray<#lib1::JSAny? /* erasure=core::Object? */>? /* erasure=_interceptors::JSArray<core::Object?>? */, #lib1::JSObject? /* erasure=_interceptors::JSObject? */]) → void);
|
||||
js_::_functionToJSN((core::int arg1, core::String arg2, #lib1::JSArray<#lib1::JSAny? /* erasure=core::Object? */> /* erasure=_interceptors::JSArray<core::Object?> */ arg3, #lib1::JSObject /* erasure=_interceptors::JSObject */ arg4, #lib1::JSPromise<#lib1::JSAny? /* erasure=core::Object? */> /* erasure=_interceptors::JSObject */ arg5, #lib1::JSAny /* erasure=core::Object */ arg6) → #lib1::JSAny /* erasure=core::Object */ => arg6, 6);
|
||||
js_::_functionToJS5(((core::int arg1, core::String arg2, #lib1::JSArray<#lib1::JSAny? /* erasure=core::Object? */> /* erasure=_interceptors::JSArray<core::Object?> */ arg3, #lib1::JSObject /* erasure=_interceptors::JSObject */ arg4, [#lib1::JSPromise<#lib1::JSAny? /* erasure=core::Object? */>? /* erasure=_interceptors::JSObject? */ arg5 = #C1, #lib1::JSAny? /* erasure=core::Object? */ arg6 = #C1]) → #lib1::JSAny? /* erasure=core::Object? */ => arg6) as (core::int, core::String, #lib1::JSArray<#lib1::JSAny? /* erasure=core::Object? */> /* erasure=_interceptors::JSArray<core::Object?> */, #lib1::JSObject /* erasure=_interceptors::JSObject */, [#lib1::JSPromise<#lib1::JSAny? /* erasure=core::Object? */>? /* erasure=_interceptors::JSObject? */]) → void);
|
||||
js_::_jsFunctionToDart(jsFunction);
|
||||
}
|
||||
|
||||
constants {
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
library;
|
||||
import self as self;
|
||||
import "dart:js_interop" as js_;
|
||||
import "dart:js_util" as js_;
|
||||
import "dart:core" as core;
|
||||
|
||||
import "dart:js_interop";
|
||||
|
||||
static method main() → void {
|
||||
js_::JSExportedDartFunction /* erasure=_interceptors::JavaScriptFunction */ jsFunction = js_::FunctionToJSExportedDartFunction|get#toJS(() → Null {});
|
||||
js_::FunctionToJSExportedDartFunction|get#toJS((core::int arg1) → core::int => arg1);
|
||||
js_::FunctionToJSExportedDartFunction|get#toJS((([core::int? arg1 = #C1]) → core::int? => arg1) as () → void);
|
||||
js_::FunctionToJSExportedDartFunction|get#toJS((core::int arg1, core::String arg2) → core::String => arg2);
|
||||
js_::FunctionToJSExportedDartFunction|get#toJS((([core::int? arg1 = #C1, core::String? arg2 = #C1]) → core::String? => arg2) as ([core::int]) → void);
|
||||
js_::FunctionToJSExportedDartFunction|get#toJS((core::int arg1, core::String arg2, js_::JSArray<js_::JSAny? /* erasure=core::Object? */> /* erasure=_interceptors::JSArray<core::Object?> */ arg3) → js_::JSArray<js_::JSAny? /* erasure=core::Object? */> /* erasure=_interceptors::JSArray<core::Object?> */ => arg3);
|
||||
js_::FunctionToJSExportedDartFunction|get#toJS(((core::int arg1, [core::String? arg2 = #C1, js_::JSArray<js_::JSAny? /* erasure=core::Object? */>? /* erasure=_interceptors::JSArray<core::Object?>? */ arg3 = #C1]) → js_::JSArray<js_::JSAny? /* erasure=core::Object? */>? /* erasure=_interceptors::JSArray<core::Object?>? */ => arg3) as (core::int, [core::String]) → void);
|
||||
js_::FunctionToJSExportedDartFunction|get#toJS((core::int arg1, core::String arg2, js_::JSArray<js_::JSAny? /* erasure=core::Object? */> /* erasure=_interceptors::JSArray<core::Object?> */ arg3, js_::JSObject /* erasure=_interceptors::JSObject */ arg4) → js_::JSObject /* erasure=_interceptors::JSObject */ => arg4);
|
||||
js_::FunctionToJSExportedDartFunction|get#toJS(((core::int arg1, core::String arg2, js_::JSArray<js_::JSAny? /* erasure=core::Object? */> /* erasure=_interceptors::JSArray<core::Object?> */ arg3, [js_::JSObject? /* erasure=_interceptors::JSObject? */ arg4 = #C1]) → js_::JSObject? /* erasure=_interceptors::JSObject? */ => arg4) as (core::int, core::String, js_::JSArray<js_::JSAny? /* erasure=core::Object? */> /* erasure=_interceptors::JSArray<core::Object?> */) → void);
|
||||
js_::FunctionToJSExportedDartFunction|get#toJS((core::int arg1, core::String arg2, js_::JSArray<js_::JSAny? /* erasure=core::Object? */> /* erasure=_interceptors::JSArray<core::Object?> */ arg3, js_::JSObject /* erasure=_interceptors::JSObject */ arg4, js_::JSPromise<js_::JSAny? /* erasure=core::Object? */> /* erasure=_interceptors::JSObject */ arg5) → js_::JSPromise<js_::JSAny? /* erasure=core::Object? */> /* erasure=_interceptors::JSObject */ => arg5);
|
||||
js_::FunctionToJSExportedDartFunction|get#toJS(((core::int arg1, core::String arg2, [js_::JSArray<js_::JSAny? /* erasure=core::Object? */>? /* erasure=_interceptors::JSArray<core::Object?>? */ arg3 = #C1, js_::JSObject? /* erasure=_interceptors::JSObject? */ arg4 = #C1, js_::JSPromise<js_::JSAny? /* erasure=core::Object? */>? /* erasure=_interceptors::JSObject? */ arg5 = #C1]) → js_::JSPromise<js_::JSAny? /* erasure=core::Object? */>? /* erasure=_interceptors::JSObject? */ => arg5) as (core::int, core::String, [js_::JSArray<js_::JSAny? /* erasure=core::Object? */>? /* erasure=_interceptors::JSArray<core::Object?>? */, js_::JSObject? /* erasure=_interceptors::JSObject? */]) → void);
|
||||
js_::FunctionToJSExportedDartFunction|get#toJS((core::int arg1, core::String arg2, js_::JSArray<js_::JSAny? /* erasure=core::Object? */> /* erasure=_interceptors::JSArray<core::Object?> */ arg3, js_::JSObject /* erasure=_interceptors::JSObject */ arg4, js_::JSPromise<js_::JSAny? /* erasure=core::Object? */> /* erasure=_interceptors::JSObject */ arg5, js_::JSAny /* erasure=core::Object */ arg6) → js_::JSAny /* erasure=core::Object */ => arg6);
|
||||
js_::FunctionToJSExportedDartFunction|get#toJS(((core::int arg1, core::String arg2, js_::JSArray<js_::JSAny? /* erasure=core::Object? */> /* erasure=_interceptors::JSArray<core::Object?> */ arg3, js_::JSObject /* erasure=_interceptors::JSObject */ arg4, [js_::JSPromise<js_::JSAny? /* erasure=core::Object? */>? /* erasure=_interceptors::JSObject? */ arg5 = #C1, js_::JSAny? /* erasure=core::Object? */ arg6 = #C1]) → js_::JSAny? /* erasure=core::Object? */ => arg6) as (core::int, core::String, js_::JSArray<js_::JSAny? /* erasure=core::Object? */> /* erasure=_interceptors::JSArray<core::Object?> */, js_::JSObject /* erasure=_interceptors::JSObject */, [js_::JSPromise<js_::JSAny? /* erasure=core::Object? */>? /* erasure=_interceptors::JSObject? */]) → void);
|
||||
js_::JSExportedDartFunctionToFunction|get#toDart(jsFunction);
|
||||
#lib1::JSExportedDartFunction /* erasure=_interceptors::JavaScriptFunction */ jsFunction = js_::_functionToJS0(() → Null {});
|
||||
js_::_functionToJS1((core::int arg1) → core::int => arg1);
|
||||
js_::_functionToJS0((([core::int? arg1 = #C1]) → core::int? => arg1) as () → void);
|
||||
js_::_functionToJS2((core::int arg1, core::String arg2) → core::String => arg2);
|
||||
js_::_functionToJS1((([core::int? arg1 = #C1, core::String? arg2 = #C1]) → core::String? => arg2) as ([core::int]) → void);
|
||||
js_::_functionToJS3((core::int arg1, core::String arg2, #lib1::JSArray<#lib1::JSAny? /* erasure=core::Object? */> /* erasure=_interceptors::JSArray<core::Object?> */ arg3) → #lib1::JSArray<#lib1::JSAny? /* erasure=core::Object? */> /* erasure=_interceptors::JSArray<core::Object?> */ => arg3);
|
||||
js_::_functionToJS2(((core::int arg1, [core::String? arg2 = #C1, #lib1::JSArray<#lib1::JSAny? /* erasure=core::Object? */>? /* erasure=_interceptors::JSArray<core::Object?>? */ arg3 = #C1]) → #lib1::JSArray<#lib1::JSAny? /* erasure=core::Object? */>? /* erasure=_interceptors::JSArray<core::Object?>? */ => arg3) as (core::int, [core::String]) → void);
|
||||
js_::_functionToJS4((core::int arg1, core::String arg2, #lib1::JSArray<#lib1::JSAny? /* erasure=core::Object? */> /* erasure=_interceptors::JSArray<core::Object?> */ arg3, #lib1::JSObject /* erasure=_interceptors::JSObject */ arg4) → #lib1::JSObject /* erasure=_interceptors::JSObject */ => arg4);
|
||||
js_::_functionToJS3(((core::int arg1, core::String arg2, #lib1::JSArray<#lib1::JSAny? /* erasure=core::Object? */> /* erasure=_interceptors::JSArray<core::Object?> */ arg3, [#lib1::JSObject? /* erasure=_interceptors::JSObject? */ arg4 = #C1]) → #lib1::JSObject? /* erasure=_interceptors::JSObject? */ => arg4) as (core::int, core::String, #lib1::JSArray<#lib1::JSAny? /* erasure=core::Object? */> /* erasure=_interceptors::JSArray<core::Object?> */) → void);
|
||||
js_::_functionToJS5((core::int arg1, core::String arg2, #lib1::JSArray<#lib1::JSAny? /* erasure=core::Object? */> /* erasure=_interceptors::JSArray<core::Object?> */ arg3, #lib1::JSObject /* erasure=_interceptors::JSObject */ arg4, #lib1::JSPromise<#lib1::JSAny? /* erasure=core::Object? */> /* erasure=_interceptors::JSObject */ arg5) → #lib1::JSPromise<#lib1::JSAny? /* erasure=core::Object? */> /* erasure=_interceptors::JSObject */ => arg5);
|
||||
js_::_functionToJS4(((core::int arg1, core::String arg2, [#lib1::JSArray<#lib1::JSAny? /* erasure=core::Object? */>? /* erasure=_interceptors::JSArray<core::Object?>? */ arg3 = #C1, #lib1::JSObject? /* erasure=_interceptors::JSObject? */ arg4 = #C1, #lib1::JSPromise<#lib1::JSAny? /* erasure=core::Object? */>? /* erasure=_interceptors::JSObject? */ arg5 = #C1]) → #lib1::JSPromise<#lib1::JSAny? /* erasure=core::Object? */>? /* erasure=_interceptors::JSObject? */ => arg5) as (core::int, core::String, [#lib1::JSArray<#lib1::JSAny? /* erasure=core::Object? */>? /* erasure=_interceptors::JSArray<core::Object?>? */, #lib1::JSObject? /* erasure=_interceptors::JSObject? */]) → void);
|
||||
js_::_functionToJSN((core::int arg1, core::String arg2, #lib1::JSArray<#lib1::JSAny? /* erasure=core::Object? */> /* erasure=_interceptors::JSArray<core::Object?> */ arg3, #lib1::JSObject /* erasure=_interceptors::JSObject */ arg4, #lib1::JSPromise<#lib1::JSAny? /* erasure=core::Object? */> /* erasure=_interceptors::JSObject */ arg5, #lib1::JSAny /* erasure=core::Object */ arg6) → #lib1::JSAny /* erasure=core::Object */ => arg6, 6);
|
||||
js_::_functionToJS5(((core::int arg1, core::String arg2, #lib1::JSArray<#lib1::JSAny? /* erasure=core::Object? */> /* erasure=_interceptors::JSArray<core::Object?> */ arg3, #lib1::JSObject /* erasure=_interceptors::JSObject */ arg4, [#lib1::JSPromise<#lib1::JSAny? /* erasure=core::Object? */>? /* erasure=_interceptors::JSObject? */ arg5 = #C1, #lib1::JSAny? /* erasure=core::Object? */ arg6 = #C1]) → #lib1::JSAny? /* erasure=core::Object? */ => arg6) as (core::int, core::String, #lib1::JSArray<#lib1::JSAny? /* erasure=core::Object? */> /* erasure=_interceptors::JSArray<core::Object?> */, #lib1::JSObject /* erasure=_interceptors::JSObject */, [#lib1::JSPromise<#lib1::JSAny? /* erasure=core::Object? */>? /* erasure=_interceptors::JSObject? */]) → void);
|
||||
js_::_jsFunctionToDart(jsFunction);
|
||||
}
|
||||
|
||||
constants {
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
library;
|
||||
import self as self;
|
||||
import "dart:js_interop" as js_;
|
||||
import "dart:js_util" as js_;
|
||||
import "dart:core" as core;
|
||||
|
||||
import "dart:js_interop";
|
||||
|
||||
static method main() → void {
|
||||
js_::JSExportedDartFunction /* erasure=dart._interceptors::JavaScriptFunction */ jsFunction = js_::FunctionToJSExportedDartFunction|get#toJS(() → Null {});
|
||||
js_::FunctionToJSExportedDartFunction|get#toJS((core::int arg1) → core::int => arg1);
|
||||
js_::FunctionToJSExportedDartFunction|get#toJS((([core::int? arg1 = #C1]) → core::int? => arg1) as () → void);
|
||||
js_::FunctionToJSExportedDartFunction|get#toJS((core::int arg1, core::String arg2) → core::String => arg2);
|
||||
js_::FunctionToJSExportedDartFunction|get#toJS((([core::int? arg1 = #C1, core::String? arg2 = #C1]) → core::String? => arg2) as ([core::int]) → void);
|
||||
js_::FunctionToJSExportedDartFunction|get#toJS((core::int arg1, core::String arg2, js_::JSArray<js_::JSAny? /* erasure=core::Object? */> /* erasure=dart._interceptors::JSArray<core::Object?> */ arg3) → js_::JSArray<js_::JSAny? /* erasure=core::Object? */> /* erasure=dart._interceptors::JSArray<core::Object?> */ => arg3);
|
||||
js_::FunctionToJSExportedDartFunction|get#toJS(((core::int arg1, [core::String? arg2 = #C1, js_::JSArray<js_::JSAny? /* erasure=core::Object? */>? /* erasure=dart._interceptors::JSArray<core::Object?>? */ arg3 = #C1]) → js_::JSArray<js_::JSAny? /* erasure=core::Object? */>? /* erasure=dart._interceptors::JSArray<core::Object?>? */ => arg3) as (core::int, [core::String]) → void);
|
||||
js_::FunctionToJSExportedDartFunction|get#toJS((core::int arg1, core::String arg2, js_::JSArray<js_::JSAny? /* erasure=core::Object? */> /* erasure=dart._interceptors::JSArray<core::Object?> */ arg3, js_::JSObject /* erasure=dart._interceptors::JSObject */ arg4) → js_::JSObject /* erasure=dart._interceptors::JSObject */ => arg4);
|
||||
js_::FunctionToJSExportedDartFunction|get#toJS(((core::int arg1, core::String arg2, js_::JSArray<js_::JSAny? /* erasure=core::Object? */> /* erasure=dart._interceptors::JSArray<core::Object?> */ arg3, [js_::JSObject? /* erasure=dart._interceptors::JSObject? */ arg4 = #C1]) → js_::JSObject? /* erasure=dart._interceptors::JSObject? */ => arg4) as (core::int, core::String, js_::JSArray<js_::JSAny? /* erasure=core::Object? */> /* erasure=dart._interceptors::JSArray<core::Object?> */) → void);
|
||||
js_::FunctionToJSExportedDartFunction|get#toJS((core::int arg1, core::String arg2, js_::JSArray<js_::JSAny? /* erasure=core::Object? */> /* erasure=dart._interceptors::JSArray<core::Object?> */ arg3, js_::JSObject /* erasure=dart._interceptors::JSObject */ arg4, js_::JSPromise<js_::JSAny? /* erasure=core::Object? */> /* erasure=dart._interceptors::JSObject */ arg5) → js_::JSPromise<js_::JSAny? /* erasure=core::Object? */> /* erasure=dart._interceptors::JSObject */ => arg5);
|
||||
js_::FunctionToJSExportedDartFunction|get#toJS(((core::int arg1, core::String arg2, [js_::JSArray<js_::JSAny? /* erasure=core::Object? */>? /* erasure=dart._interceptors::JSArray<core::Object?>? */ arg3 = #C1, js_::JSObject? /* erasure=dart._interceptors::JSObject? */ arg4 = #C1, js_::JSPromise<js_::JSAny? /* erasure=core::Object? */>? /* erasure=dart._interceptors::JSObject? */ arg5 = #C1]) → js_::JSPromise<js_::JSAny? /* erasure=core::Object? */>? /* erasure=dart._interceptors::JSObject? */ => arg5) as (core::int, core::String, [js_::JSArray<js_::JSAny? /* erasure=core::Object? */>? /* erasure=dart._interceptors::JSArray<core::Object?>? */, js_::JSObject? /* erasure=dart._interceptors::JSObject? */]) → void);
|
||||
js_::FunctionToJSExportedDartFunction|get#toJS((core::int arg1, core::String arg2, js_::JSArray<js_::JSAny? /* erasure=core::Object? */> /* erasure=dart._interceptors::JSArray<core::Object?> */ arg3, js_::JSObject /* erasure=dart._interceptors::JSObject */ arg4, js_::JSPromise<js_::JSAny? /* erasure=core::Object? */> /* erasure=dart._interceptors::JSObject */ arg5, js_::JSAny /* erasure=core::Object */ arg6) → js_::JSAny /* erasure=core::Object */ => arg6);
|
||||
js_::FunctionToJSExportedDartFunction|get#toJS(((core::int arg1, core::String arg2, js_::JSArray<js_::JSAny? /* erasure=core::Object? */> /* erasure=dart._interceptors::JSArray<core::Object?> */ arg3, js_::JSObject /* erasure=dart._interceptors::JSObject */ arg4, [js_::JSPromise<js_::JSAny? /* erasure=core::Object? */>? /* erasure=dart._interceptors::JSObject? */ arg5 = #C1, js_::JSAny? /* erasure=core::Object? */ arg6 = #C1]) → js_::JSAny? /* erasure=core::Object? */ => arg6) as (core::int, core::String, js_::JSArray<js_::JSAny? /* erasure=core::Object? */> /* erasure=dart._interceptors::JSArray<core::Object?> */, js_::JSObject /* erasure=dart._interceptors::JSObject */, [js_::JSPromise<js_::JSAny? /* erasure=core::Object? */>? /* erasure=dart._interceptors::JSObject? */]) → void);
|
||||
js_::JSExportedDartFunctionToFunction|get#toDart(jsFunction);
|
||||
#lib1::JSExportedDartFunction /* erasure=dart._interceptors::JavaScriptFunction */ jsFunction = js_::_functionToJS0(() → Null {});
|
||||
js_::_functionToJS1((core::int arg1) → core::int => arg1);
|
||||
js_::_functionToJS0((([core::int? arg1 = #C1]) → core::int? => arg1) as () → void);
|
||||
js_::_functionToJS2((core::int arg1, core::String arg2) → core::String => arg2);
|
||||
js_::_functionToJS1((([core::int? arg1 = #C1, core::String? arg2 = #C1]) → core::String? => arg2) as ([core::int]) → void);
|
||||
js_::_functionToJS3((core::int arg1, core::String arg2, #lib1::JSArray<#lib1::JSAny? /* erasure=core::Object? */> /* erasure=dart._interceptors::JSArray<core::Object?> */ arg3) → #lib1::JSArray<#lib1::JSAny? /* erasure=core::Object? */> /* erasure=dart._interceptors::JSArray<core::Object?> */ => arg3);
|
||||
js_::_functionToJS2(((core::int arg1, [core::String? arg2 = #C1, #lib1::JSArray<#lib1::JSAny? /* erasure=core::Object? */>? /* erasure=dart._interceptors::JSArray<core::Object?>? */ arg3 = #C1]) → #lib1::JSArray<#lib1::JSAny? /* erasure=core::Object? */>? /* erasure=dart._interceptors::JSArray<core::Object?>? */ => arg3) as (core::int, [core::String]) → void);
|
||||
js_::_functionToJS4((core::int arg1, core::String arg2, #lib1::JSArray<#lib1::JSAny? /* erasure=core::Object? */> /* erasure=dart._interceptors::JSArray<core::Object?> */ arg3, #lib1::JSObject /* erasure=dart._interceptors::JSObject */ arg4) → #lib1::JSObject /* erasure=dart._interceptors::JSObject */ => arg4);
|
||||
js_::_functionToJS3(((core::int arg1, core::String arg2, #lib1::JSArray<#lib1::JSAny? /* erasure=core::Object? */> /* erasure=dart._interceptors::JSArray<core::Object?> */ arg3, [#lib1::JSObject? /* erasure=dart._interceptors::JSObject? */ arg4 = #C1]) → #lib1::JSObject? /* erasure=dart._interceptors::JSObject? */ => arg4) as (core::int, core::String, #lib1::JSArray<#lib1::JSAny? /* erasure=core::Object? */> /* erasure=dart._interceptors::JSArray<core::Object?> */) → void);
|
||||
js_::_functionToJS5((core::int arg1, core::String arg2, #lib1::JSArray<#lib1::JSAny? /* erasure=core::Object? */> /* erasure=dart._interceptors::JSArray<core::Object?> */ arg3, #lib1::JSObject /* erasure=dart._interceptors::JSObject */ arg4, #lib1::JSPromise<#lib1::JSAny? /* erasure=core::Object? */> /* erasure=dart._interceptors::JSObject */ arg5) → #lib1::JSPromise<#lib1::JSAny? /* erasure=core::Object? */> /* erasure=dart._interceptors::JSObject */ => arg5);
|
||||
js_::_functionToJS4(((core::int arg1, core::String arg2, [#lib1::JSArray<#lib1::JSAny? /* erasure=core::Object? */>? /* erasure=dart._interceptors::JSArray<core::Object?>? */ arg3 = #C1, #lib1::JSObject? /* erasure=dart._interceptors::JSObject? */ arg4 = #C1, #lib1::JSPromise<#lib1::JSAny? /* erasure=core::Object? */>? /* erasure=dart._interceptors::JSObject? */ arg5 = #C1]) → #lib1::JSPromise<#lib1::JSAny? /* erasure=core::Object? */>? /* erasure=dart._interceptors::JSObject? */ => arg5) as (core::int, core::String, [#lib1::JSArray<#lib1::JSAny? /* erasure=core::Object? */>? /* erasure=dart._interceptors::JSArray<core::Object?>? */, #lib1::JSObject? /* erasure=dart._interceptors::JSObject? */]) → void);
|
||||
js_::_functionToJSN((core::int arg1, core::String arg2, #lib1::JSArray<#lib1::JSAny? /* erasure=core::Object? */> /* erasure=dart._interceptors::JSArray<core::Object?> */ arg3, #lib1::JSObject /* erasure=dart._interceptors::JSObject */ arg4, #lib1::JSPromise<#lib1::JSAny? /* erasure=core::Object? */> /* erasure=dart._interceptors::JSObject */ arg5, #lib1::JSAny /* erasure=core::Object */ arg6) → #lib1::JSAny /* erasure=core::Object */ => arg6, 6);
|
||||
js_::_functionToJS5(((core::int arg1, core::String arg2, #lib1::JSArray<#lib1::JSAny? /* erasure=core::Object? */> /* erasure=dart._interceptors::JSArray<core::Object?> */ arg3, #lib1::JSObject /* erasure=dart._interceptors::JSObject */ arg4, [#lib1::JSPromise<#lib1::JSAny? /* erasure=core::Object? */>? /* erasure=dart._interceptors::JSObject? */ arg5 = #C1, #lib1::JSAny? /* erasure=core::Object? */ arg6 = #C1]) → #lib1::JSAny? /* erasure=core::Object? */ => arg6) as (core::int, core::String, #lib1::JSArray<#lib1::JSAny? /* erasure=core::Object? */> /* erasure=dart._interceptors::JSArray<core::Object?> */, #lib1::JSObject /* erasure=dart._interceptors::JSObject */, [#lib1::JSPromise<#lib1::JSAny? /* erasure=core::Object? */>? /* erasure=dart._interceptors::JSObject? */]) → void);
|
||||
js_::_jsFunctionToDart(jsFunction);
|
||||
}
|
||||
|
||||
constants {
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
// Patch file for dart:js_util library.
|
||||
import 'dart:_foreign_helper' show JS;
|
||||
import 'dart:_interceptors' show JavaScriptFunction;
|
||||
import 'dart:_internal' show patch;
|
||||
import 'dart:_runtime' as dart;
|
||||
|
||||
|
@ -46,3 +47,254 @@ Function allowInteropCaptureThis(Function f) {
|
|||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// TODO(srujzs): In dart2js, this is guaranteed to be unique per isolate. DDC
|
||||
// doesn't have a mechanism to guarantee that, so use a Symbol instead to match
|
||||
// the unique-per-runtime semantics of [allowInterop].
|
||||
final _functionToJSPropertyName = r'_$dart_dartClosure';
|
||||
final _functionToJSProperty = JS('!', "Symbol($_functionToJSPropertyName)");
|
||||
|
||||
JavaScriptFunction _functionToJS0(Function f) {
|
||||
// This can only happen if a user casted a JavaScriptFunction to Function.
|
||||
// Such a cast is an error in dart2wasm, so we should make this behavior an
|
||||
// error as well.
|
||||
if (!dart.isDartFunction(f)) {
|
||||
throw ArgumentError('Attempting to rewrap a JS function.');
|
||||
}
|
||||
final ret = JS<JavaScriptFunction>(
|
||||
'!',
|
||||
'''
|
||||
function () {
|
||||
return #(#);
|
||||
}
|
||||
''',
|
||||
_callDartFunctionFast0,
|
||||
f);
|
||||
JS('', '#[#] = #', ret, _functionToJSProperty, f);
|
||||
return ret;
|
||||
}
|
||||
|
||||
JavaScriptFunction _functionToJS1(Function f) {
|
||||
if (!dart.isDartFunction(f)) {
|
||||
throw ArgumentError('Attempting to rewrap a JS function.');
|
||||
}
|
||||
final ret = JS<JavaScriptFunction>(
|
||||
'!',
|
||||
'''
|
||||
function (arg1) {
|
||||
return #(#, arg1, arguments.length);
|
||||
}
|
||||
''',
|
||||
_callDartFunctionFast1,
|
||||
f);
|
||||
JS('', '#[#] = #', ret, _functionToJSProperty, f);
|
||||
return ret;
|
||||
}
|
||||
|
||||
JavaScriptFunction _functionToJS2(Function f) {
|
||||
if (!dart.isDartFunction(f)) {
|
||||
throw ArgumentError('Attempting to rewrap a JS function.');
|
||||
}
|
||||
final ret = JS<JavaScriptFunction>(
|
||||
'!',
|
||||
'''
|
||||
function (arg1, arg2) {
|
||||
return #(#, arg1, arg2, arguments.length);
|
||||
}
|
||||
''',
|
||||
_callDartFunctionFast2,
|
||||
f);
|
||||
JS('', '#[#] = #', ret, _functionToJSProperty, f);
|
||||
return ret;
|
||||
}
|
||||
|
||||
JavaScriptFunction _functionToJS3(Function f) {
|
||||
if (!dart.isDartFunction(f)) {
|
||||
throw ArgumentError('Attempting to rewrap a JS function.');
|
||||
}
|
||||
final ret = JS<JavaScriptFunction>(
|
||||
'!',
|
||||
'''
|
||||
function (arg1, arg2, arg3) {
|
||||
return #(#, arg1, arg2, arg3, arguments.length);
|
||||
}
|
||||
''',
|
||||
_callDartFunctionFast3,
|
||||
f);
|
||||
JS('', '#[#] = #', ret, _functionToJSProperty, f);
|
||||
return ret;
|
||||
}
|
||||
|
||||
JavaScriptFunction _functionToJS4(Function f) {
|
||||
if (!dart.isDartFunction(f)) {
|
||||
throw ArgumentError('Attempting to rewrap a JS function.');
|
||||
}
|
||||
final ret = JS<JavaScriptFunction>(
|
||||
'!',
|
||||
'''
|
||||
function (arg1, arg2, arg3, arg4) {
|
||||
return #(#, arg1, arg2, arg3, arg4, arguments.length);
|
||||
}
|
||||
''',
|
||||
_callDartFunctionFast4,
|
||||
f);
|
||||
JS('', '#[#] = #', ret, _functionToJSProperty, f);
|
||||
return ret;
|
||||
}
|
||||
|
||||
JavaScriptFunction _functionToJS5(Function f) {
|
||||
if (!dart.isDartFunction(f)) {
|
||||
throw ArgumentError('Attempting to rewrap a JS function.');
|
||||
}
|
||||
final ret = JS<JavaScriptFunction>(
|
||||
'!',
|
||||
'''
|
||||
function (arg1, arg2, arg3, arg4, arg5) {
|
||||
return #(#, arg1, arg2, arg3, arg4, arg5, arguments.length);
|
||||
}
|
||||
''',
|
||||
_callDartFunctionFast5,
|
||||
f);
|
||||
JS('', '#[#] = #', ret, _functionToJSProperty, f);
|
||||
return ret;
|
||||
}
|
||||
|
||||
JavaScriptFunction _functionToJSN(Function f, int maxLength) {
|
||||
if (!dart.isDartFunction(f)) {
|
||||
throw ArgumentError('Attempting to rewrap a JS function.');
|
||||
}
|
||||
final ret = JS<JavaScriptFunction>(
|
||||
'!',
|
||||
'''
|
||||
function (...args) {
|
||||
return #(#, Array.prototype.slice.call(args, 0,
|
||||
Math.min(args.length, #)));
|
||||
}
|
||||
''',
|
||||
dart.dcall,
|
||||
f,
|
||||
maxLength);
|
||||
JS('', '#[#] = #', ret, _functionToJSProperty, f);
|
||||
return ret;
|
||||
}
|
||||
|
||||
_callDartFunctionFast0(callback) => JS('', '#()', callback);
|
||||
|
||||
_callDartFunctionFast1(callback, arg1, int length) {
|
||||
if (length >= 1) {
|
||||
final error =
|
||||
dart.validateFunctionToJSArgs(callback, JS<List>('!', '[#]', arg1));
|
||||
if (error != null) return error;
|
||||
return JS('', '#(#)', callback, arg1);
|
||||
} else {
|
||||
final error = dart.validateFunctionToJSArgs(callback, JS<List>('!', '[]'));
|
||||
if (error != null) return error;
|
||||
return JS('', '#()', callback);
|
||||
}
|
||||
}
|
||||
|
||||
_callDartFunctionFast2(callback, arg1, arg2, int length) {
|
||||
if (length >= 2) {
|
||||
final error = dart.validateFunctionToJSArgs(
|
||||
callback, JS<List>('!', '[#, #]', arg1, arg2));
|
||||
if (error != null) return error;
|
||||
return JS('', '#(#, #)', callback, arg1, arg2);
|
||||
} else if (length == 1) {
|
||||
final error =
|
||||
dart.validateFunctionToJSArgs(callback, JS<List>('!', '[#]', arg1));
|
||||
if (error != null) return error;
|
||||
return JS('', '#(#)', callback, arg1);
|
||||
} else {
|
||||
final error = dart.validateFunctionToJSArgs(callback, JS<List>('!', '[]'));
|
||||
if (error != null) return error;
|
||||
return JS('', '#()', callback);
|
||||
}
|
||||
}
|
||||
|
||||
_callDartFunctionFast3(callback, arg1, arg2, arg3, int length) {
|
||||
if (length >= 3) {
|
||||
final error = dart.validateFunctionToJSArgs(
|
||||
callback, JS<List>('!', '[#, #, #]', arg1, arg2, arg3));
|
||||
if (error != null) return error;
|
||||
return JS('', '#(#, #, #)', callback, arg1, arg2, arg3);
|
||||
} else if (length == 2) {
|
||||
final error = dart.validateFunctionToJSArgs(
|
||||
callback, JS<List>('!', '[#, #]', arg1, arg2));
|
||||
if (error != null) return error;
|
||||
return JS('', '#(#, #)', callback, arg1, arg2);
|
||||
} else if (length == 1) {
|
||||
final error =
|
||||
dart.validateFunctionToJSArgs(callback, JS<List>('!', '[#]', arg1));
|
||||
if (error != null) return error;
|
||||
return JS('', '#(#)', callback, arg1);
|
||||
} else {
|
||||
final error = dart.validateFunctionToJSArgs(callback, JS<List>('!', '[]'));
|
||||
if (error != null) return error;
|
||||
return JS('', '#()', callback);
|
||||
}
|
||||
}
|
||||
|
||||
_callDartFunctionFast4(callback, arg1, arg2, arg3, arg4, int length) {
|
||||
if (length >= 4) {
|
||||
final error = dart.validateFunctionToJSArgs(
|
||||
callback, JS<List>('!', '[#, #, #, #]', arg1, arg2, arg3, arg4));
|
||||
if (error != null) return error;
|
||||
return JS('', '#(#, #, #, #)', callback, arg1, arg2, arg3, arg4);
|
||||
} else if (length == 3) {
|
||||
final error = dart.validateFunctionToJSArgs(
|
||||
callback, JS<List>('!', '[#, #, #]', arg1, arg2, arg3));
|
||||
if (error != null) return error;
|
||||
return JS('', '#(#, #, #)', callback, arg1, arg2, arg3);
|
||||
} else if (length == 2) {
|
||||
final error = dart.validateFunctionToJSArgs(
|
||||
callback, JS<List>('!', '[#, #]', arg1, arg2));
|
||||
if (error != null) return error;
|
||||
return JS('', '#(#, #)', callback, arg1, arg2);
|
||||
} else if (length == 1) {
|
||||
final error =
|
||||
dart.validateFunctionToJSArgs(callback, JS<List>('!', '[#]', arg1));
|
||||
if (error != null) return error;
|
||||
return JS('', '#(#)', callback, arg1);
|
||||
} else {
|
||||
final error = dart.validateFunctionToJSArgs(callback, JS<List>('!', '[]'));
|
||||
if (error != null) return error;
|
||||
return JS('', '#()', callback);
|
||||
}
|
||||
}
|
||||
|
||||
_callDartFunctionFast5(callback, arg1, arg2, arg3, arg4, arg5, int length) {
|
||||
if (length >= 5) {
|
||||
final error = dart.validateFunctionToJSArgs(callback,
|
||||
JS<List>('!', '[#, #, #, #, #]', arg1, arg2, arg3, arg4, arg5));
|
||||
if (error != null) return error;
|
||||
return JS('', '#(#, #, #, #, #)', callback, arg1, arg2, arg3, arg4, arg5);
|
||||
} else if (length == 4) {
|
||||
final error = dart.validateFunctionToJSArgs(
|
||||
callback, JS<List>('!', '[#, #, #, #]', arg1, arg2, arg3, arg4));
|
||||
if (error != null) return error;
|
||||
return JS('', '#(#, #, #, #)', callback, arg1, arg2, arg3, arg4);
|
||||
} else if (length == 3) {
|
||||
final error = dart.validateFunctionToJSArgs(
|
||||
callback, JS<List>('!', '[#, #, #]', arg1, arg2, arg3));
|
||||
if (error != null) return error;
|
||||
return JS('', '#(#, #, #)', callback, arg1, arg2, arg3);
|
||||
} else if (length == 2) {
|
||||
final error = dart.validateFunctionToJSArgs(
|
||||
callback, JS<List>('!', '[#, #]', arg1, arg2));
|
||||
if (error != null) return error;
|
||||
return JS('', '#(#, #)', callback, arg1, arg2);
|
||||
} else if (length == 1) {
|
||||
final error =
|
||||
dart.validateFunctionToJSArgs(callback, JS<List>('!', '[#]', arg1));
|
||||
if (error != null) return error;
|
||||
return JS('', '#(#)', callback, arg1);
|
||||
} else {
|
||||
final error = dart.validateFunctionToJSArgs(callback, JS<List>('!', '[]'));
|
||||
if (error != null) return error;
|
||||
return JS('', '#()', callback);
|
||||
}
|
||||
}
|
||||
|
||||
Function _jsFunctionToDart(JavaScriptFunction f) {
|
||||
return JS('Function', '#[#]', f, _functionToJSProperty);
|
||||
}
|
||||
|
|
|
@ -428,6 +428,26 @@ _checkAndCall(f, ftype, obj, typeArgs, args, named, displayName) {
|
|||
return callNSM(errorMessage);
|
||||
}
|
||||
|
||||
/// Given a Dart function [f] that was wrapped in a `Function.toJS` call, and
|
||||
/// the corresponding [args] used to call it, validates that the arity and types
|
||||
/// of [args] are correct.
|
||||
///
|
||||
/// Returns null if it's valid call and a [noSuchMethod] invocation with the
|
||||
/// specific error otherwise.
|
||||
validateFunctionToJSArgs(f, List args) {
|
||||
var errorMessage = _argumentErrors(
|
||||
JS<Object>('', '#[#]', f, JS_GET_NAME(JsGetName.SIGNATURE_NAME)),
|
||||
args,
|
||||
null);
|
||||
if (errorMessage != null) {
|
||||
return noSuchMethod(
|
||||
f,
|
||||
InvocationImpl(JS('', 'f.name'), args,
|
||||
isMethod: true, failureMessage: errorMessage));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
dcall(f, args, [@undefined named]) => _checkAndCall(
|
||||
f, null, JS('', 'void 0'), null, args, named, JS('', 'f.name'));
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
// 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:_interceptors' show DART_CLOSURE_PROPERTY_NAME, JavaScriptFunction;
|
||||
import 'dart:_internal' show patch;
|
||||
import 'dart:_js_helper'
|
||||
show
|
||||
|
@ -80,3 +80,187 @@ Function allowInteropCaptureThis(Function f) {
|
|||
return _convertDartFunctionFastCaptureThis(f);
|
||||
}
|
||||
}
|
||||
|
||||
JavaScriptFunction _functionToJS0(Function f) {
|
||||
// This can only happen if a user casted a JavaScriptFunction to Function.
|
||||
// Such a cast is an error in dart2wasm, so we should make this behavior an
|
||||
// error as well.
|
||||
if (isJSFunction(f)) {
|
||||
throw ArgumentError('Attempting to rewrap a JS function.');
|
||||
}
|
||||
final result = JS(
|
||||
'JavaScriptFunction',
|
||||
'''
|
||||
function(_call, f) {
|
||||
return function() {
|
||||
return _call(f);
|
||||
}
|
||||
}(#, #)
|
||||
''',
|
||||
DART_CLOSURE_TO_JS(_callDartFunctionFast0),
|
||||
f);
|
||||
JS('', '#.# = #', result, DART_CLOSURE_PROPERTY_NAME, f);
|
||||
return result;
|
||||
}
|
||||
|
||||
JavaScriptFunction _functionToJS1(Function f) {
|
||||
if (isJSFunction(f)) {
|
||||
throw ArgumentError('Attempting to rewrap a JS function.');
|
||||
}
|
||||
final result = JS(
|
||||
'JavaScriptFunction',
|
||||
'''
|
||||
function(_call, f) {
|
||||
return function(arg1) {
|
||||
return _call(f, arg1, arguments.length);
|
||||
}
|
||||
}(#, #)
|
||||
''',
|
||||
DART_CLOSURE_TO_JS(_callDartFunctionFast1),
|
||||
f);
|
||||
JS('', '#.# = #', result, DART_CLOSURE_PROPERTY_NAME, f);
|
||||
return result;
|
||||
}
|
||||
|
||||
JavaScriptFunction _functionToJS2(Function f) {
|
||||
if (isJSFunction(f)) {
|
||||
throw ArgumentError('Attempting to rewrap a JS function.');
|
||||
}
|
||||
final result = JS(
|
||||
'JavaScriptFunction',
|
||||
'''
|
||||
function(_call, f) {
|
||||
return function(arg1, arg2) {
|
||||
return _call(f, arg1, arg2, arguments.length);
|
||||
}
|
||||
}(#, #)
|
||||
''',
|
||||
DART_CLOSURE_TO_JS(_callDartFunctionFast2),
|
||||
f);
|
||||
JS('', '#.# = #', result, DART_CLOSURE_PROPERTY_NAME, f);
|
||||
return result;
|
||||
}
|
||||
|
||||
JavaScriptFunction _functionToJS3(Function f) {
|
||||
if (isJSFunction(f)) {
|
||||
throw ArgumentError('Attempting to rewrap a JS function.');
|
||||
}
|
||||
final result = JS(
|
||||
'JavaScriptFunction',
|
||||
'''
|
||||
function(_call, f) {
|
||||
return function(arg1, arg2, arg3) {
|
||||
return _call(f, arg1, arg2, arg3, arguments.length);
|
||||
}
|
||||
}(#, #)
|
||||
''',
|
||||
DART_CLOSURE_TO_JS(_callDartFunctionFast3),
|
||||
f);
|
||||
JS('', '#.# = #', result, DART_CLOSURE_PROPERTY_NAME, f);
|
||||
return result;
|
||||
}
|
||||
|
||||
JavaScriptFunction _functionToJS4(Function f) {
|
||||
if (isJSFunction(f)) {
|
||||
throw ArgumentError('Attempting to rewrap a JS function.');
|
||||
}
|
||||
final result = JS(
|
||||
'JavaScriptFunction',
|
||||
'''
|
||||
function(_call, f) {
|
||||
return function(arg1, arg2, arg3, arg4) {
|
||||
return _call(f, arg1, arg2, arg3, arg4, arguments.length);
|
||||
}
|
||||
}(#, #)
|
||||
''',
|
||||
DART_CLOSURE_TO_JS(_callDartFunctionFast4),
|
||||
f);
|
||||
JS('', '#.# = #', result, DART_CLOSURE_PROPERTY_NAME, f);
|
||||
return result;
|
||||
}
|
||||
|
||||
JavaScriptFunction _functionToJS5(Function f) {
|
||||
if (isJSFunction(f)) {
|
||||
throw ArgumentError('Attempting to rewrap a JS function.');
|
||||
}
|
||||
final result = JS(
|
||||
'JavaScriptFunction',
|
||||
'''
|
||||
function(_call, f) {
|
||||
return function(arg1, arg2, arg3, arg4, arg5) {
|
||||
return _call(f, arg1, arg2, arg3, arg4, arg5, arguments.length);
|
||||
}
|
||||
}(#, #)
|
||||
''',
|
||||
DART_CLOSURE_TO_JS(_callDartFunctionFast5),
|
||||
f);
|
||||
JS('', '#.# = #', result, DART_CLOSURE_PROPERTY_NAME, f);
|
||||
return result;
|
||||
}
|
||||
|
||||
JavaScriptFunction _functionToJSN(Function f, int maxLength) {
|
||||
if (isJSFunction(f)) {
|
||||
throw ArgumentError('Attempting to rewrap a JS function.');
|
||||
}
|
||||
final result = JS(
|
||||
'JavaScriptFunction',
|
||||
'''
|
||||
function(_call, f, maxLength) {
|
||||
return function () {
|
||||
return _call(f, Array.prototype.slice.call(arguments, 0,
|
||||
Math.min(arguments.length, maxLength)));
|
||||
}
|
||||
}(#, #, #)
|
||||
''',
|
||||
DART_CLOSURE_TO_JS(_callDartFunctionFastN),
|
||||
f,
|
||||
maxLength);
|
||||
JS('', '#.# = #', result, DART_CLOSURE_PROPERTY_NAME, f);
|
||||
return result;
|
||||
}
|
||||
|
||||
_callDartFunctionFast0(Function callback) => callback();
|
||||
|
||||
_callDartFunctionFast1(Function callback, arg1, int length) {
|
||||
if (length >= 1) return callback(arg1);
|
||||
return callback();
|
||||
}
|
||||
|
||||
_callDartFunctionFast2(Function callback, arg1, arg2, int length) {
|
||||
if (length >= 2) return callback(arg1, arg2);
|
||||
if (length == 1) return callback(arg1);
|
||||
return callback();
|
||||
}
|
||||
|
||||
_callDartFunctionFast3(Function callback, arg1, arg2, arg3, int length) {
|
||||
if (length >= 3) return callback(arg1, arg2, arg3);
|
||||
if (length == 2) return callback(arg1, arg2);
|
||||
if (length == 1) return callback(arg1);
|
||||
return callback();
|
||||
}
|
||||
|
||||
_callDartFunctionFast4(Function callback, arg1, arg2, arg3, arg4, int length) {
|
||||
if (length >= 4) return callback(arg1, arg2, arg3, arg4);
|
||||
if (length == 3) return callback(arg1, arg2, arg3);
|
||||
if (length == 2) return callback(arg1, arg2);
|
||||
if (length == 1) return callback(arg1);
|
||||
return callback();
|
||||
}
|
||||
|
||||
_callDartFunctionFast5(
|
||||
Function callback, arg1, arg2, arg3, arg4, arg5, int length) {
|
||||
if (length >= 5) return callback(arg1, arg2, arg3, arg4, arg5);
|
||||
if (length == 4) return callback(arg1, arg2, arg3, arg4);
|
||||
if (length == 3) return callback(arg1, arg2, arg3);
|
||||
if (length == 2) return callback(arg1, arg2);
|
||||
if (length == 1) return callback(arg1);
|
||||
return callback();
|
||||
}
|
||||
|
||||
_callDartFunctionFastN(Function callback, List arguments) {
|
||||
return Function.apply(callback, arguments);
|
||||
}
|
||||
|
||||
Function _jsFunctionToDart(JavaScriptFunction f) {
|
||||
return JS('Function', '#.#', f, DART_CLOSURE_PROPERTY_NAME);
|
||||
}
|
||||
|
|
|
@ -65,19 +65,18 @@ extension NullableObjectUtilExtension on Object? {
|
|||
// JSExportedDartFunction <-> Function
|
||||
@patch
|
||||
extension JSExportedDartFunctionToFunction on JSExportedDartFunction {
|
||||
// TODO(srujzs): We should unwrap rather than allow arbitrary JS functions
|
||||
// to be called in Dart.
|
||||
@patch
|
||||
@pragma('dart2js:prefer-inline')
|
||||
Function get toDart => this._jsFunction;
|
||||
Function get toDart => throw UnimplementedError(
|
||||
"'toDart' should never directly be called. Calls to 'toDart' should have "
|
||||
'been transformed by the interop transformer.');
|
||||
}
|
||||
|
||||
@patch
|
||||
extension FunctionToJSExportedDartFunction on Function {
|
||||
@patch
|
||||
@pragma('dart2js:prefer-inline')
|
||||
JSExportedDartFunction get toJS =>
|
||||
js_util.allowInterop(this) as JSExportedDartFunction;
|
||||
JSExportedDartFunction get toJS => throw UnimplementedError(
|
||||
"'toJS' should never directly be called. Calls to 'toJS' should have "
|
||||
'been transformed by the interop transformer.');
|
||||
}
|
||||
|
||||
// Embedded global property for wrapped Dart objects passed via JS interop.
|
||||
|
|
|
@ -477,7 +477,8 @@ extension JSFunctionUtilExtension on JSFunction {
|
|||
extension JSExportedDartFunctionToFunction on JSExportedDartFunction {
|
||||
/// The Dart [Function] that this [JSExportedDartFunction] wrapped.
|
||||
///
|
||||
/// Must be a wrapped Dart [Function].
|
||||
/// Must be a function that was wrapped with
|
||||
/// [FunctionToJSExportedDartFunction.toJS].
|
||||
external Function get toDart;
|
||||
}
|
||||
|
||||
|
@ -490,6 +491,15 @@ extension FunctionToJSExportedDartFunction on Function {
|
|||
/// compile. See
|
||||
/// https://dart.dev/interop/js-interop/js-types#requirements-on-external-declarations-and-function-tojs
|
||||
/// for more details on what types are allowed.
|
||||
///
|
||||
/// The max number of arguments that are passed to this [Function] from the
|
||||
/// wrapper JavaScript function is determined by this [Function]'s static
|
||||
/// type. Any extra arguments passed to the JavaScript function after the max
|
||||
/// number of arguments are discarded like they are with regular JavaScript
|
||||
/// functions.
|
||||
///
|
||||
/// Calling this on the same [Function] again will always result in a new
|
||||
/// JavaScript function.
|
||||
external JSExportedDartFunction get toJS;
|
||||
}
|
||||
|
||||
|
|
453
tests/lib/js/static_interop_test/js_function_arity_test.dart
Normal file
453
tests/lib/js/static_interop_test/js_function_arity_test.dart
Normal file
|
@ -0,0 +1,453 @@
|
|||
// Copyright (c) 2024, 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.
|
||||
|
||||
/// Requirements=checked-implicit-downcasts
|
||||
|
||||
import 'dart:js_interop';
|
||||
|
||||
import 'package:expect/expect.dart';
|
||||
|
||||
const isDDC = const bool.fromEnvironment('dart.library._ddc_only');
|
||||
const isDart2JS = const bool.fromEnvironment('dart.tool.dart2js');
|
||||
|
||||
@JS('call')
|
||||
external String _call(JSFunction f, JSArray<JSAny?> args);
|
||||
|
||||
String call(JSFunction f, List<Object?> args) =>
|
||||
_call(f, args.map((e) => e?.jsify()).toList().toJS);
|
||||
|
||||
@JS()
|
||||
external void eval(String code);
|
||||
|
||||
// Zero.
|
||||
String zeroArgs() => '0';
|
||||
|
||||
// One.
|
||||
String oneRequired(String arg1) => arg1;
|
||||
String oneOptional([String arg1 = 'default']) => '$arg1';
|
||||
|
||||
// Two.
|
||||
String twoRequired(String arg1, String? arg2) => '$arg1$arg2';
|
||||
String oneRequiredOneOptional(String arg1, [String? arg2 = 'default']) =>
|
||||
'$arg1$arg2';
|
||||
String twoOptional([String arg1 = 'default', String? arg2 = 'default']) =>
|
||||
'$arg1$arg2';
|
||||
|
||||
// Three.
|
||||
String threeRequired(String arg1, String? arg2, String arg3) =>
|
||||
'$arg1$arg2$arg3';
|
||||
String twoRequiredOneOptional(String arg1, String? arg2,
|
||||
[String arg3 = 'default']) =>
|
||||
'$arg1$arg2$arg3';
|
||||
String oneRequiredTwoOptional(String arg1,
|
||||
[String? arg2 = 'default', String arg3 = 'default']) =>
|
||||
'$arg1$arg2$arg3';
|
||||
String threeOptional(
|
||||
[String arg1 = 'default',
|
||||
String? arg2 = 'default',
|
||||
String arg3 = 'default']) =>
|
||||
'$arg1$arg2$arg3';
|
||||
|
||||
// Four.
|
||||
String fourRequired(String arg1, String? arg2, String arg3, String arg4) =>
|
||||
'$arg1$arg2$arg3$arg4';
|
||||
String threeRequiredOneOptional(String arg1, String? arg2, String arg3,
|
||||
[String arg4 = 'default']) =>
|
||||
'$arg1$arg2$arg3$arg4';
|
||||
String twoRequiredTwoOptional(String arg1, String? arg2,
|
||||
[String arg3 = 'default', String arg4 = 'default']) =>
|
||||
'$arg1$arg2$arg3$arg4';
|
||||
String oneRequiredThreeOptional(String arg1,
|
||||
[String? arg2 = 'default',
|
||||
String arg3 = 'default',
|
||||
String arg4 = 'default']) =>
|
||||
'$arg1$arg2$arg3$arg4';
|
||||
String fourOptional(
|
||||
[String arg1 = 'default',
|
||||
String? arg2 = 'default',
|
||||
String arg3 = 'default',
|
||||
String arg4 = 'default']) =>
|
||||
'$arg1$arg2$arg3$arg4';
|
||||
|
||||
// Five.
|
||||
String fiveRequired(
|
||||
String arg1, String? arg2, String arg3, String arg4, String arg5) =>
|
||||
'$arg1$arg2$arg3$arg4$arg5';
|
||||
String fourRequiredOneOptional(
|
||||
String arg1, String? arg2, String arg3, String arg4,
|
||||
[String arg5 = 'default']) =>
|
||||
'$arg1$arg2$arg3$arg4$arg5';
|
||||
String threeRequiredTwoOptional(String arg1, String? arg2, String arg3,
|
||||
[String arg4 = 'default', String arg5 = 'default']) =>
|
||||
'$arg1$arg2$arg3$arg4$arg5';
|
||||
String twoRequiredThreeOptional(String arg1, String? arg2,
|
||||
[String arg3 = 'default',
|
||||
String arg4 = 'default',
|
||||
String arg5 = 'default']) =>
|
||||
'$arg1$arg2$arg3$arg4$arg5';
|
||||
String oneRequiredFourOptional(String arg1,
|
||||
[String? arg2 = 'default',
|
||||
String arg3 = 'default',
|
||||
String arg4 = 'default',
|
||||
String arg5 = 'default']) =>
|
||||
'$arg1$arg2$arg3$arg4$arg5';
|
||||
String fiveOptional(
|
||||
[String arg1 = 'default',
|
||||
String? arg2 = 'default',
|
||||
String arg3 = 'default',
|
||||
String arg4 = 'default',
|
||||
String arg5 = 'default']) =>
|
||||
'$arg1$arg2$arg3$arg4$arg5';
|
||||
|
||||
// Six.
|
||||
String sixRequired(String arg1, String? arg2, String arg3, String arg4,
|
||||
String arg5, String arg6) =>
|
||||
'$arg1$arg2$arg3$arg4$arg5$arg6';
|
||||
String fiveRequiredOneOptional(
|
||||
String arg1, String? arg2, String arg3, String arg4, String arg5,
|
||||
[String arg6 = 'default']) =>
|
||||
'$arg1$arg2$arg3$arg4$arg5$arg6';
|
||||
String fourRequiredTwoOptional(
|
||||
String arg1, String? arg2, String arg3, String arg4,
|
||||
[String arg5 = 'default', String arg6 = 'default']) =>
|
||||
'$arg1$arg2$arg3$arg4$arg5$arg6';
|
||||
String threeRequiredThreeOptional(String arg1, String? arg2, String arg3,
|
||||
[String arg4 = 'default',
|
||||
String arg5 = 'default',
|
||||
String arg6 = 'default']) =>
|
||||
'$arg1$arg2$arg3$arg4$arg5$arg6';
|
||||
String twoRequiredFourOptional(String arg1, String? arg2,
|
||||
[String arg3 = 'default',
|
||||
String arg4 = 'default',
|
||||
String arg5 = 'default',
|
||||
String arg6 = 'default']) =>
|
||||
'$arg1$arg2$arg3$arg4$arg5$arg6';
|
||||
String oneRequiredFiveOptional(String arg1,
|
||||
[String? arg2 = 'default',
|
||||
String arg3 = 'default',
|
||||
String arg4 = 'default',
|
||||
String arg5 = 'default',
|
||||
String arg6 = 'default']) =>
|
||||
'$arg1$arg2$arg3$arg4$arg5$arg6';
|
||||
String sixOptional(
|
||||
[String arg1 = 'default',
|
||||
String? arg2 = 'default',
|
||||
String arg3 = 'default',
|
||||
String arg4 = 'default',
|
||||
String arg5 = 'default',
|
||||
String arg6 = 'default']) =>
|
||||
'$arg1$arg2$arg3$arg4$arg5$arg6';
|
||||
|
||||
void testZero() {
|
||||
// Arity tests.
|
||||
Expect.equals(call(zeroArgs.toJS, []), '0');
|
||||
Expect.equals(call(zeroArgs.toJS, ['extra']), '0');
|
||||
Expect.equals(call(zeroArgs.toJS, [1.0]), '0');
|
||||
|
||||
// Conversion round-trip test.
|
||||
final tearOff = zeroArgs;
|
||||
Expect.equals(tearOff, tearOff.toJS.toDart);
|
||||
|
||||
// Avoid rewrapping test.
|
||||
if (isDDC || isDart2JS) {
|
||||
Expect.throws(() => (zeroArgs.toJS as String Function()).toJS);
|
||||
}
|
||||
}
|
||||
|
||||
void testOne() {
|
||||
// Type tests.
|
||||
Expect.throws(() => call(oneRequired.toJS, [0]));
|
||||
Expect.throwsWhen(hasSoundNullSafety, () => call(oneOptional.toJS, [null]));
|
||||
Expect.throwsWhen(
|
||||
hasSoundNullSafety, () => call(oneOptional.toJS, ['undefined']));
|
||||
|
||||
// Arity tests.
|
||||
Expect.throws(() => call(oneRequired.toJS, []));
|
||||
Expect.equals(call(oneRequired.toJS, ['a']), 'a');
|
||||
Expect.equals(call(oneRequired.toJS, ['a', 'extra']), 'a');
|
||||
Expect.equals(call(oneOptional.toJS, []), 'default');
|
||||
Expect.equals(call(oneOptional.toJS, ['a']), 'a');
|
||||
Expect.equals(call(oneOptional.toJS, ['a', 'extra']), 'a');
|
||||
|
||||
// Function subtyping tests.
|
||||
Expect.equals(call((oneOptional as String Function()).toJS, []), 'default');
|
||||
// Throws away the additional args due to the static typing.
|
||||
Expect.equals(
|
||||
call((oneOptional as String Function()).toJS, ['a']), 'default');
|
||||
|
||||
// Conversion round-trip test.
|
||||
final tearOff = oneRequired;
|
||||
Expect.equals(tearOff, tearOff.toJS.toDart);
|
||||
|
||||
// Avoid rewrapping test.
|
||||
if (isDDC || isDart2JS) {
|
||||
Expect.throws(() => (oneOptional.toJS as String Function()).toJS);
|
||||
}
|
||||
}
|
||||
|
||||
void testTwo() {
|
||||
// Type tests.
|
||||
Expect.throws(() => call(twoOptional.toJS, [false, 'b']));
|
||||
Expect.throws(() => call(twoOptional.toJS, ['a', 1.0]));
|
||||
Expect.throwsWhen(hasSoundNullSafety,
|
||||
() => call(oneRequiredOneOptional.toJS, ['undefined', 'b']));
|
||||
Expect.throws(() => call(oneRequiredOneOptional.toJS, ['a', true]));
|
||||
Expect.throws(() => call(twoRequired.toJS, [0, 'b']));
|
||||
Expect.throws(() => call(twoRequired.toJS, ['a', 0]));
|
||||
|
||||
// Arity tests.
|
||||
Expect.throws(() => call(twoRequired.toJS, []));
|
||||
Expect.throws(() => call(twoRequired.toJS, ['a']));
|
||||
Expect.equals(call(twoRequired.toJS, ['a', 'b']), 'ab');
|
||||
Expect.equals(call(twoRequired.toJS, ['a', 'b', 'extra']), 'ab');
|
||||
Expect.throws(() => call(oneRequiredOneOptional.toJS, []));
|
||||
Expect.equals(call(oneRequiredOneOptional.toJS, ['a']), 'adefault');
|
||||
Expect.equals(call(oneRequiredOneOptional.toJS, ['a', 'b']), 'ab');
|
||||
Expect.equals(call(oneRequiredOneOptional.toJS, ['a', 'b', 'extra']), 'ab');
|
||||
Expect.equals(call(twoOptional.toJS, []), 'defaultdefault');
|
||||
Expect.equals(call(twoOptional.toJS, ['a']), 'adefault');
|
||||
Expect.equals(call(twoOptional.toJS, ['a', 'b']), 'ab');
|
||||
Expect.equals(call(twoOptional.toJS, ['a', 'b', 'extra']), 'ab');
|
||||
|
||||
// Function subtyping tests.
|
||||
// TODO(55881): dart2wasm's type conversions are based on the static type,
|
||||
// whereas DDC and dart2js only do type checks based on the runtime type. We
|
||||
// can't replicate dart2Wasm's behavior in DDC and dart2js as it would require
|
||||
// a new Dart trampoline for every function, so there's a discrepancy when we
|
||||
// use a static type with different parameter types.
|
||||
var closure = () =>
|
||||
call((twoRequired as String Function(String, String)).toJS, ['a', null]);
|
||||
if (isDDC || isDart2JS) {
|
||||
Expect.equals(closure(), 'anull');
|
||||
} else {
|
||||
Expect.throws(closure);
|
||||
}
|
||||
Expect.throws(
|
||||
() => call((oneRequiredOneOptional as String Function(String)).toJS, []));
|
||||
Expect.equals(
|
||||
call((oneRequiredOneOptional as String Function(String)).toJS, ['a']),
|
||||
'adefault');
|
||||
Expect.equals(
|
||||
call((oneRequiredOneOptional as String Function(String)).toJS, ['a', 0]),
|
||||
'adefault');
|
||||
Expect.equals(
|
||||
call((twoOptional as String Function()).toJS, []), 'defaultdefault');
|
||||
Expect.equals(
|
||||
call((twoOptional as String Function()).toJS, ['a']), 'defaultdefault');
|
||||
Expect.equals(call((twoOptional as String Function([String])).toJS, []),
|
||||
'defaultdefault');
|
||||
Expect.equals(
|
||||
call((twoOptional as String Function([String])).toJS, ['a']), 'adefault');
|
||||
Expect.equals(
|
||||
call((twoOptional as String Function([String])).toJS, ['a', false]),
|
||||
'adefault');
|
||||
|
||||
// `undefined` tests.
|
||||
Expect.equals(call(twoRequired.toJS, ['a', 'undefined']), 'anull');
|
||||
// TODO(55884): DDC lowers function with defaults to use the JS default
|
||||
// argument syntax, which means passing `undefined` results in DDC replacing
|
||||
// it with the default, instead of keeping it as `undefined`.
|
||||
Expect.equals(call(oneRequiredOneOptional.toJS, ['a', 'undefined']),
|
||||
isDDC ? 'adefault' : 'anull');
|
||||
Expect.equals(
|
||||
call(twoOptional.toJS, ['a', 'undefined']), isDDC ? 'adefault' : 'anull');
|
||||
|
||||
// Conversion round-trip test.
|
||||
final tearOff = twoRequired;
|
||||
Expect.equals(tearOff, tearOff.toJS.toDart);
|
||||
|
||||
// Avoid rewrapping test.
|
||||
if (isDDC || isDart2JS) {
|
||||
Expect.throws(
|
||||
() => (oneRequiredOneOptional.toJS as String Function()).toJS);
|
||||
}
|
||||
}
|
||||
|
||||
// To avoid making this test unreadably long, the remaining tests choose a small
|
||||
// subset of all possible tests for general validation.
|
||||
void testThree() {
|
||||
// Type tests.
|
||||
Expect.throws(() => call(threeRequired.toJS, [0, 'b', 'c']));
|
||||
Expect.throws(() => call(oneRequiredTwoOptional.toJS, ['a', false]));
|
||||
|
||||
// Arity tests.
|
||||
Expect.equals(call(twoRequiredOneOptional.toJS, ['a', 'b']), 'abdefault');
|
||||
Expect.throws(() => call(oneRequiredTwoOptional.toJS, []));
|
||||
|
||||
// Function subtyping tests.
|
||||
var closure = () => call(
|
||||
(twoRequiredOneOptional as String Function(String, String)).toJS,
|
||||
['a', null, 'c']);
|
||||
if (isDDC || isDart2JS) {
|
||||
Expect.equals(closure(), 'anulldefault');
|
||||
} else {
|
||||
Expect.throws(closure);
|
||||
}
|
||||
Expect.equals(
|
||||
call((threeOptional as String Function([String])).toJS, ['a', 0, true]),
|
||||
'adefaultdefault');
|
||||
|
||||
// `undefined` tests.
|
||||
Expect.equals(call(threeOptional.toJS, ['a', 'undefined']),
|
||||
isDDC ? 'adefaultdefault' : 'anulldefault');
|
||||
|
||||
// Conversion round-trip test.
|
||||
final tearOff = threeRequired;
|
||||
Expect.equals(tearOff, tearOff.toJS.toDart);
|
||||
|
||||
// Avoid rewrapping test.
|
||||
if (isDDC || isDart2JS) {
|
||||
Expect.throws(
|
||||
() => (twoRequiredOneOptional.toJS as String Function()).toJS);
|
||||
}
|
||||
}
|
||||
|
||||
void testFour() {
|
||||
// Type tests.
|
||||
Expect.throws(
|
||||
() => call(threeRequiredOneOptional.toJS, ['a', 'b', 'c', true]));
|
||||
Expect.throws(() => call(oneRequiredThreeOptional.toJS, [false]));
|
||||
|
||||
// Arity tests.
|
||||
Expect.equals(call(fourRequired.toJS, ['a', 'b', 'c', 'd', false]), 'abcd');
|
||||
Expect.equals(call(fourOptional.toJS, ['a']), 'adefaultdefaultdefault');
|
||||
|
||||
// Function subtyping tests.
|
||||
final closure = () => call(
|
||||
(threeRequiredOneOptional as String Function(String, String, String))
|
||||
.toJS,
|
||||
['a', null, 'c']);
|
||||
if (isDDC || isDart2JS) {
|
||||
Expect.equals(closure(), 'anullcdefault');
|
||||
} else {
|
||||
Expect.throws(closure);
|
||||
}
|
||||
Expect.equals(
|
||||
call(
|
||||
(twoRequiredTwoOptional as String Function(String, String?, [String]))
|
||||
.toJS,
|
||||
['a', null]),
|
||||
'anulldefaultdefault');
|
||||
|
||||
// `undefined` tests.
|
||||
Expect.equals(call(oneRequiredThreeOptional.toJS, ['a', 'undefined', 'c']),
|
||||
isDDC ? 'adefaultcdefault' : 'anullcdefault');
|
||||
|
||||
// Conversion round-trip test.
|
||||
final tearOff = fourRequired;
|
||||
Expect.equals(tearOff, tearOff.toJS.toDart);
|
||||
|
||||
// Avoid rewrapping test.
|
||||
if (isDDC || isDart2JS) {
|
||||
Expect.throws(
|
||||
() => (oneRequiredThreeOptional.toJS as String Function()).toJS);
|
||||
}
|
||||
}
|
||||
|
||||
void testFive() {
|
||||
// Type tests.
|
||||
Expect.throws(() => call(twoRequiredThreeOptional.toJS, ['a', 0]));
|
||||
Expect.throws(() => call(fiveOptional.toJS, [false]));
|
||||
|
||||
// Arity tests.
|
||||
Expect.equals(call(fiveRequired.toJS, ['a', 'b', 'c', 'd', 'e', 0]), 'abcde');
|
||||
Expect.equals(call(fourRequiredOneOptional.toJS, ['a', null, 'c', 'd']),
|
||||
'anullcddefault');
|
||||
|
||||
// Function subtyping tests.
|
||||
final closure = () => call(
|
||||
(threeRequiredTwoOptional as String Function(String, String, String,
|
||||
[String]))
|
||||
.toJS,
|
||||
['a', null, 'c']);
|
||||
if (isDDC || isDart2JS) {
|
||||
Expect.equals(closure(), 'anullcdefaultdefault');
|
||||
} else {
|
||||
Expect.throws(closure);
|
||||
}
|
||||
Expect.equals(
|
||||
call(
|
||||
(twoRequiredThreeOptional as String Function(String, String?,
|
||||
[String]))
|
||||
.toJS,
|
||||
['a', null, 'c']),
|
||||
'anullcdefaultdefault');
|
||||
|
||||
// `undefined` tests.
|
||||
Expect.equals(
|
||||
call(oneRequiredFourOptional.toJS, ['a', 'undefined', 'c', 'd', 'e']),
|
||||
isDDC ? 'adefaultcde' : 'anullcde');
|
||||
|
||||
// Conversion round-trip test.
|
||||
final tearOff = fiveRequired;
|
||||
Expect.equals(tearOff, tearOff.toJS.toDart);
|
||||
|
||||
// Avoid rewrapping test.
|
||||
if (isDDC || isDart2JS) {
|
||||
Expect.throws(
|
||||
() => (twoRequiredThreeOptional.toJS as String Function()).toJS);
|
||||
}
|
||||
}
|
||||
|
||||
// DDC and dart2js should use either a `dcall` or `Function.apply` for this.
|
||||
void testSix() {
|
||||
// Type tests.
|
||||
Expect.throws(() => call(sixRequired.toJS, ['a', 'b', 0.0, 'd', 'e', 'f']));
|
||||
Expect.throws(() => call(threeRequiredThreeOptional.toJS, ['undefined']));
|
||||
|
||||
// Arity tests.
|
||||
// Verify that we appropriately truncate arguments even though we don't have
|
||||
// a special lowering for six arguments in DDC and dart2js.
|
||||
Expect.equals(
|
||||
call(fourRequiredTwoOptional.toJS, ['a', 'b', 'c', 'd', 'e', 'f', 0]),
|
||||
'abcdef');
|
||||
Expect.throws(() => call(twoRequiredFourOptional.toJS, []));
|
||||
|
||||
// Function subtyping tests.
|
||||
var closure = () => call(
|
||||
(fiveRequiredOneOptional as String Function(
|
||||
String, String, String, String, String))
|
||||
.toJS,
|
||||
['a', null, 'c', 'd', 'e', 'f']);
|
||||
if (isDDC || isDart2JS) {
|
||||
Expect.equals(closure(), 'anullcdedefault');
|
||||
} else {
|
||||
Expect.throws(closure);
|
||||
}
|
||||
Expect.equals(
|
||||
call((oneRequiredFiveOptional as String Function(String, [String?])).toJS,
|
||||
['a', 'b', 0, 0.0, false]),
|
||||
'abdefaultdefaultdefaultdefault');
|
||||
|
||||
// `undefined` tests.
|
||||
Expect.equals(call(sixOptional.toJS, ['a', 'undefined', 'c', 'd', 'e']),
|
||||
isDDC ? 'adefaultcdedefault' : 'anullcdedefault');
|
||||
|
||||
// Conversion round-trip test.
|
||||
final tearOff = sixRequired;
|
||||
Expect.equals(tearOff, tearOff.toJS.toDart);
|
||||
|
||||
// Avoid rewrapping test.
|
||||
if (isDDC || isDart2JS) {
|
||||
Expect.throws(() => (sixOptional.toJS as String Function()).toJS);
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
eval('''
|
||||
self.call = function(f, args) {
|
||||
var convert = function(arg) {
|
||||
return arg == 'undefined' ? undefined : arg;
|
||||
};
|
||||
return f.apply(null, args.map((e) => convert(e)));
|
||||
};
|
||||
''');
|
||||
testZero();
|
||||
testOne();
|
||||
testTwo();
|
||||
testThree();
|
||||
testFour();
|
||||
testFive();
|
||||
testSix();
|
||||
}
|
|
@ -156,15 +156,20 @@ void syncTests() {
|
|||
expect(confuse(fun) is JSFunction, true);
|
||||
|
||||
// [JSExportedDartFunction] <-> [Function]
|
||||
edf = (JSString a, JSString b) {
|
||||
final dartFunction = (JSString a, JSString b) {
|
||||
return (a.toDart + b.toDart).toJS;
|
||||
}.toJS;
|
||||
};
|
||||
edf = dartFunction.toJS;
|
||||
expect(doFun('foo'.toJS, 'bar'.toJS).toDart, 'foobar');
|
||||
expect(
|
||||
(edf.toDart as JSString Function(JSString, JSString))(
|
||||
'foo'.toJS, 'bar'.toJS)
|
||||
.toDart,
|
||||
'foobar');
|
||||
Expect.equals(edf.toDart, dartFunction);
|
||||
Expect.isTrue(identical(edf.toDart, dartFunction));
|
||||
// Two wrappers should not be the same.
|
||||
Expect.notEquals(edf, dartFunction.toJS);
|
||||
// Converting a non-function should throw.
|
||||
Expect.throws(() => ('foo'.toJS as JSExportedDartFunction).toDart);
|
||||
|
||||
|
|
|
@ -90,6 +90,7 @@ js/static_interop_test/isa/functional_test: SkipByDesign # Issue 42085. CSP poli
|
|||
js/static_interop_test/isa/library_renaming_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
|
||||
js/static_interop_test/js_array_proxy_or_ref_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
|
||||
js/static_interop_test/js_array_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
|
||||
js/static_interop_test/js_function_arity_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
|
||||
js/static_interop_test/js_function_conversions_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
|
||||
js/static_interop_test/js_typed_array_test: SkipByDesign # CSP policy disallows injected JS code
|
||||
js/static_interop_test/jsobject_type_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
|
||||
|
|
Loading…
Reference in New Issue
Block a user