$$ 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 {
    TRACE_EVENT0("cobalt::script::mozjs", "MozjsCallbackFunction::Run");
    CallbackResult<R> callback_result;
    JSAutoRequest auto_request(context_);
    JS::RootedObject function(context_, weak_function_.Get());
    if (!function) {
      DLOG(WARNING) << "Function was garbage collected.";
      callback_result.exception = true;
    } else {
      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_
