invokeModule function

dynamic invokeModule(
  1. Pointer<Void> callbackContext,
  2. WebFController controller,
  3. String moduleName,
  4. String method,
  5. dynamic params,
  6. Pointer<Uint8> errmsg,
  7. Pointer<NativeFunction<NativeAsyncModuleCallback>> callback,
)

Implementation

dynamic invokeModule(Pointer<Void> callbackContext, WebFController controller, String moduleName, String method, params,
    Pointer<Uint8> errmsg, Pointer<NativeFunction<NativeAsyncModuleCallback>> callback) {
  WebFViewController currentView = controller.view;
  dynamic result;

  Stopwatch? stopwatch;
  if (enableWebFCommandLog) {
    stopwatch = Stopwatch()..start();
  }

  try {
    Future<dynamic> invokeModuleCallback({String? error, data}) {
      Completer<dynamic> completer = Completer();
      // To make sure Promise then() and catch() executed before Promise callback called at JavaScript side.
      // We should make callback always async.
      Future.microtask(() {
        if (controller.view != currentView || currentView.disposed || callback == nullptr) return;

        Pointer<NativeFunction<NativeHandleInvokeModuleResult>> handleResult =
            Pointer.fromFunction(_handleInvokeModuleResult);
        if (error != null) {
          Pointer<Utf8> errmsgPtr = error.toNativeUtf8();
          _InvokeModuleResultContext context = _InvokeModuleResultContext(
              completer, currentView, moduleName, method, params,
              errmsgPtr: errmsgPtr, stopwatch: stopwatch);
          DartAsyncModuleCallback fn = callback.asFunction();

          fn(callbackContext, currentView.contextId, errmsgPtr, nullptr, context, handleResult);
        } else {
          Pointer<NativeValue> dataPtr = malloc.allocate(sizeOf<NativeValue>());
          toNativeValue(dataPtr, data);
          _InvokeModuleResultContext context = _InvokeModuleResultContext(
              completer, currentView, moduleName, method, params,
              data: dataPtr, stopwatch: stopwatch);
          DartAsyncModuleCallback fn = callback.asFunction();
          fn(callbackContext, currentView.contextId, nullptr, dataPtr, context, handleResult);
        }

        // Add fallbacks for handing result was not returned.
        Timer(Duration(seconds: 1), () {
          if (!completer.isCompleted) {
            completer.complete();
          }
        });
      });
      return completer.future;
    }

    result = controller.module.moduleManager.invokeModule(moduleName, method, params, invokeModuleCallback);
  } catch (e, stack) {
    if (enableWebFCommandLog) {
      bridgeLogger.severe('Invoke module failed', e, stack);
    }
    String error = '$e\n$stack';

    if (callback == nullptr) {
      final msgList = errmsg.asTypedList(1024);
      Uint8List bytes = utf8.encode(error);
      int max = bytes.length > 1020 ? 1020 : bytes.length;
      msgList.setAll(0, bytes.sublist(0, max));
      msgList[max + 1] = 0;
    } else {
      DartAsyncModuleCallback fn = callback.asFunction();
      fn(callbackContext, currentView.contextId, error.toNativeUtf8(), nullptr, {}, nullptr);
    }
  }

  if (enableWebFCommandLog) {
    bridgeLogger.fine('Invoke module name: $moduleName method: $method, params: $params '
        'return: $result time: ${stopwatch!.elapsedMicroseconds}us');
  }

  return result;
}