/**
   * Implements evaluate with additional context and destination group id operation. The
   * implementation modifies a global object.
   *
   * @param destinationValueLoader value loader that corresponds to the destination group
   * @param evaluateCommandHandler provides a particular request type
   */
  public RelayOk evaluateAsync(
      String expression,
      Map<String, ? extends SerializableValue> additionalContext,
      WipValueLoader destinationValueLoader,
      EvaluateCommandHandler<?> evaluateCommandHandler,
      final JsEvaluateContext.EvaluateCallback callback,
      SyncCallback syncCallback) {

    RelaySyncCallback relaySyncCallback = new RelaySyncCallback(syncCallback);

    final EvaluateSession evaluateSession =
        new EvaluateSession(
            expression, additionalContext, destinationValueLoader, evaluateCommandHandler);

    final RelaySyncCallback.Guard guard = relaySyncCallback.newGuard();

    GenericCallback<Void> postEnsureCallback =
        new GenericCallback<Void>() {
          @Override
          public void success(Void value) {
            RelayOk relayOk = evaluateSession.run(callback, guard.getRelay());
            guard.discharge(relayOk);
          }

          @Override
          public void failure(Exception exception) {
            if (callback != null) {
              callback.failure(exception);
            }
          }
        };

    return ensureObjectInjected(postEnsureCallback, guard.asSyncCallback());
  }
 /**
  * Makes sure that we injected a helper object inside a global object. This cannot be implemented
  * as step in {@link WipRelayRunner}, because the method is synchronized and cannot undergo
  * required control inversion.
  */
 private synchronized RelayOk ensureObjectInjected(
     GenericCallback<Void> callback, SyncCallback syncCallback) {
   if (objectInjected) {
     callback.success(null);
     return RelaySyncCallback.finish(syncCallback);
   } else {
     objectInjected = true;
     return injectObject(callback, syncCallback);
   }
 }