$$ This is a pump file for generating file templates.  Pump is a python
$$ script that is part of the Google Test suite of utilities.  Description
$$ can be found here:
$$
$$ http://code.google.com/p/googletest/wiki/PumpManual
$$

$$ This should be no larger than MAX_ARITY in base/bind.h.pump.
$var MAX_ARITY = 7
/*
 * Copyright 2016 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// clang-format off

#ifndef COBALT_SCRIPT_MOZJS_MOZJS_CALLBACK_FUNCTION_H_
#define COBALT_SCRIPT_MOZJS_MOZJS_CALLBACK_FUNCTION_H_

#include "base/logging.h"
#include "cobalt/script/callback_function.h"
#include "cobalt/script/mozjs/conversion_helpers.h"
#include "cobalt/script/mozjs/convert_callback_return_value.h"
#include "cobalt/script/mozjs/weak_heap_object.h"
#include "third_party/mozjs/js/src/jsapi.h"
#include "third_party/mozjs/js/src/jscntxt.h"

namespace cobalt {
namespace script {
namespace mozjs {

// First, we forward declare the Callback class template. This informs the
// compiler that the template only has 1 type parameter which is the base
// CallbackFunction template class with parameters.
//
// See base/callback.h.pump for further discussion on this pattern.
template <typename Sig>
class MozjsCallbackFunction;

$range ARITY 0..MAX_ARITY
$for ARITY [[
$range ARG 1..ARITY


$if ARITY == 0 [[
template <typename R>
class MozjsCallbackFunction<R(void)>
    : public CallbackFunction<R(void)> {
]] $else [[
template <typename R, $for ARG , [[typename A$(ARG)]]>
class MozjsCallbackFunction<R($for ARG , [[A$(ARG)]])>
    : public CallbackFunction<R($for ARG , [[A$(ARG)]])> {
]]

 public:
  typedef CallbackFunction<R($for ARG , [[A$(ARG)]])> BaseType;

  explicit MozjsCallbackFunction(JSContext* context, JS::HandleObject function)
      : context_(context), weak_function_(context, function) {
    DCHECK(context_);
    DCHECK(JS_ObjectIsFunction(context_, function));
  }

  CallbackResult<R> Run($for ARG , [[

      typename base::internal::CallbackParamTraits<A$(ARG)>::ForwardType a$(ARG)]])
      const OVERRIDE {
    CallbackResult<R> callback_result;
    JS::RootedObject function(context_, weak_function_.Get());
    if (!function) {
      DLOG(WARNING) << "Function was garbage collected.";
      callback_result.exception = true;
    } else {
      JSAutoRequest auto_request(context_);
      JSAutoCompartment auto_compartment(context_, function);
      JSExceptionState* previous_exception_state =
          JS_SaveExceptionState(context_);

      // https://www.w3.org/TR/WebIDL/#es-invoking-callback-functions
      // Callback 'this' is set to null, unless overridden by other specifications
      JS::Value this_value(JS::NullValue());
      JS::RootedValue return_value(context_);
      const int kNumArguments = $(ARITY);


$if ARITY > 0 [[
      JS::Value args[$(ARITY)];
      js::SetValueRangeToNull(args, kNumArguments);
      js::AutoValueArray auto_array_rooter(context_, args, kNumArguments);
      $for ARG [[ToJSValue(context_, a$(ARG), auto_array_rooter.handleAt($(ARG - 1)));
      ]]

      JSBool call_result = JS::Call(context_, this_value, function,
          kNumArguments, args, return_value.address());
]] $else [[
      JSBool call_result = JS::Call(context_, this_value, function, 0, NULL,
          return_value.address());
]]

      if (!call_result) {
        DLOG(WARNING) << "Exception in callback.";
        callback_result.exception = true;
      } else {
        callback_result = ConvertCallbackReturnValue<R>(context_, return_value);
      }
      JS_RestoreExceptionState(context_, previous_exception_state);
    }
    return callback_result;
  }

  JSObject* handle() const { return weak_function_.Get(); }

 private:
  JSContext* context_;
  WeakHeapObject weak_function_;
};

]]

template <typename Signature>
struct TypeTraits<CallbackFunction<Signature> > {
  typedef MozjsUserObjectHolder<MozjsCallbackFunction<Signature> > ConversionType;
  typedef const ScriptObject<CallbackFunction<Signature> >* ReturnType;
};

}  // namespace mozjs
}  // namespace script
}  // namespace cobalt

#endif  // COBALT_SCRIPT_MOZJS_MOZJS_CALLBACK_FUNCTION_H_
