mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 17:59:39 +00:00
[js_runtime] Use Function.prototype.bind for convertDartClosureToJS
Change-Id: Ib7142e894959994b296dee7ecc3aaf15feb0af66 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/316100 Reviewed-by: Mayank Patke <fishythefish@google.com> Commit-Queue: Stephen Adams <sra@google.com>
This commit is contained in:
parent
d02097bd1e
commit
0223d07de4
|
@ -1936,7 +1936,7 @@ int getLength(var array) {
|
|||
return JS('int', r'#.length', array);
|
||||
}
|
||||
|
||||
invokeClosure(Function closure, int numberOfArguments, var arg1, var arg2,
|
||||
_invokeClosure(Function closure, int numberOfArguments, var arg1, var arg2,
|
||||
var arg3, var arg4) {
|
||||
switch (numberOfArguments) {
|
||||
case 0:
|
||||
|
@ -1955,12 +1955,52 @@ invokeClosure(Function closure, int numberOfArguments, var arg1, var arg2,
|
|||
|
||||
/// Called by generated code to convert a Dart closure to a JS
|
||||
/// closure when the Dart closure is passed to the DOM.
|
||||
convertDartClosureToJS(closure, int arity) {
|
||||
convertDartClosureToJS(Object? closure, int arity) {
|
||||
if (closure == null) return null;
|
||||
var function = JS('var', r'#.$identity', closure);
|
||||
if (JS('bool', r'!!#', function)) return function;
|
||||
function = convertDartClosureToJSUncached(closure, arity);
|
||||
JS('void', r'#.$identity = #', closure, function);
|
||||
return function;
|
||||
}
|
||||
|
||||
function = JS(
|
||||
convertDartClosureToJSUncached(Object closure, int arity) {
|
||||
// dart2js closures are objects with a separate JavaScript method 'entry
|
||||
// point' per arity, `call$1`, `call$2` etc. The entry points have no optional
|
||||
// parameters so additional arguments at the call site will be ignored. This
|
||||
// lets us simply use `Function.prototype.bind` to pass the closed values that
|
||||
// are stored in the closure class object.
|
||||
|
||||
Object? entry;
|
||||
switch (arity) {
|
||||
case 0:
|
||||
entry = JS('', '#[#]', closure, JS_GET_NAME(JsGetName.CALL_PREFIX0));
|
||||
case 1:
|
||||
entry = JS('', '#[#]', closure, JS_GET_NAME(JsGetName.CALL_PREFIX1));
|
||||
case 2:
|
||||
entry = JS('', '#[#]', closure, JS_GET_NAME(JsGetName.CALL_PREFIX2));
|
||||
case 3:
|
||||
entry = JS('', '#[#]', closure, JS_GET_NAME(JsGetName.CALL_PREFIX3));
|
||||
case 4:
|
||||
entry = JS('', '#[#]', closure, JS_GET_NAME(JsGetName.CALL_PREFIX4));
|
||||
}
|
||||
if (entry != null) {
|
||||
return JS('', '#.bind(#)', entry, closure);
|
||||
}
|
||||
|
||||
// The above is an optimization for the following technique.
|
||||
//
|
||||
// If the entry is missing (or the above fast path is removed) the wrapped
|
||||
// closure is a JavaScript function that uses `_invokeClosure` to call the
|
||||
// Dart closure. In addition to providing a default wrapping implementation,
|
||||
// the following code causes both `closure` and `_invokeClosure` to
|
||||
// escape. Escaping both ensures the compiler should connect the escaping
|
||||
// `closure` with the call sites in `_invokeClosure`, preventing the entry
|
||||
// points of `closure` from being tree-shaken. (dart2js's current analysis is
|
||||
// the code enqueuer which is less precise, using only the presence of the
|
||||
// call sites in `_invokeClosure` to retain the entry points).
|
||||
|
||||
return JS(
|
||||
'var',
|
||||
r'''
|
||||
(function(closure, arity, invoke) {
|
||||
|
@ -1970,10 +2010,7 @@ convertDartClosureToJS(closure, int arity) {
|
|||
})(#,#,#)''',
|
||||
closure,
|
||||
arity,
|
||||
DART_CLOSURE_TO_JS(invokeClosure));
|
||||
|
||||
JS('void', r'#.$identity = #', closure, function);
|
||||
return function;
|
||||
DART_CLOSURE_TO_JS(_invokeClosure));
|
||||
}
|
||||
|
||||
/// Superclass for Dart closures.
|
||||
|
|
Loading…
Reference in a new issue