/*
 * 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.
 */

#include "cobalt/script/mozjs-45/wrapper_private.h"

#include "cobalt/script/mozjs-45/mozjs_global_environment.h"
#include "cobalt/script/mozjs-45/proxy_handler.h"
#include "cobalt/script/mozjs-45/referenced_object_map.h"
#include "third_party/mozjs-45/js/src/jsapi.h"
#include "third_party/mozjs-45/js/src/jsfun.h"
#include "third_party/mozjs-45/js/src/proxy/Proxy.h"
#include "third_party/mozjs-45/js/src/vm/NativeObject.h"

namespace cobalt {
namespace script {
namespace mozjs {

Wrappable* WrapperPrivate::GetOpaqueRoot() const {
  if (!get_opaque_root_function_.is_null()) {
    return get_opaque_root_function_.Run(wrappable_);
  }
  return NULL;
}

void WrapperPrivate::GetReachableWrappables(
    std::vector<Wrappable*>* reachable) {
  if (!get_reachable_wrappables_function_.is_null()) {
    return get_reachable_wrappables_function_.Run(wrappable_, reachable);
  }
}

bool WrapperPrivate::ShouldKeepWrapperAliveIfReachable() {
  const ProxyHandler* proxy_handler =
      base::polymorphic_downcast<const ProxyHandler*>(
          js::GetProxyHandler(wrapper_proxy_));

  DCHECK(proxy_handler);
  return proxy_handler->has_custom_property() ||
         wrappable_->ShouldKeepWrapperAlive();
}

// static
void WrapperPrivate::AddPrivateData(
    JSContext* context, JS::HandleObject wrapper_proxy,
    const scoped_refptr<Wrappable>& wrappable,
    const GetOpaqueRootFunction& get_opaque_root_function,
    const GetReachableWrappablesFunction& get_reachable_wrappables_function) {
  DCHECK(js::IsProxy(wrapper_proxy));
  WrapperPrivate* private_data = new WrapperPrivate(
      context, wrappable, wrapper_proxy, get_opaque_root_function,
      get_reachable_wrappables_function);
  JS::RootedObject target_object(context,
                                 js::GetProxyTargetObject(wrapper_proxy));
  JS_SetPrivate(target_object, private_data);
  DCHECK_EQ(JS_GetPrivate(target_object), private_data);
}

// static
bool WrapperPrivate::HasWrapperPrivate(JSContext* context,
                                       JS::HandleObject object) {
  if (js::IsProxy(object)) {
    JS::RootedObject target_object(context, js::GetProxyTargetObject(object));
    return WrapperPrivate::HasWrapperPrivate(context, target_object);
  }

  DCHECK(object->isNative());
  return object->as<js::NativeObject>().hasPrivate();
}

// static
WrapperPrivate* WrapperPrivate::GetFromWrappable(
    const scoped_refptr<Wrappable>& wrappable, JSContext* context,
    WrapperFactory* wrapper_factory) {
  JS::RootedObject wrapper_proxy(context,
                                 wrapper_factory->GetWrapperProxy(wrappable));
  WrapperPrivate* private_data = GetFromProxyObject(context, wrapper_proxy);
  DCHECK(private_data);
  DCHECK_EQ(private_data->wrappable_, wrappable);
  return private_data;
}

// static
WrapperPrivate* WrapperPrivate::GetFromWrapperObject(JS::HandleObject wrapper) {
  DCHECK(!js::IsProxy(wrapper));
  WrapperPrivate* private_data =
      static_cast<WrapperPrivate*>(JS_GetPrivate(wrapper));
  DCHECK(private_data);
  return private_data;
}

// static
WrapperPrivate* WrapperPrivate::GetFromProxyObject(
    JSContext* context, JS::HandleObject proxy_object) {
  DCHECK(js::IsProxy(proxy_object));
  JS::RootedObject target(context, js::GetProxyTargetObject(proxy_object));
  return GetFromWrapperObject(target);
}

// static
WrapperPrivate* WrapperPrivate::GetFromObject(JSContext* context,
                                              JS::HandleObject object) {
  if (js::IsProxy(object)) {
    return GetFromProxyObject(context, object);
  } else {
    return GetFromWrapperObject(object);
  }
}

// static
void WrapperPrivate::Finalizer(JSFreeOp* /* free_op */, JSObject* object) {
  WrapperPrivate* wrapper_private =
      reinterpret_cast<WrapperPrivate*>(JS_GetPrivate(object));
  DCHECK(wrapper_private);
  delete wrapper_private;
}

// static
void WrapperPrivate::Trace(JSTracer* trace, JSObject* object) {
  WrapperPrivate* wrapper_private =
      reinterpret_cast<WrapperPrivate*>(JS_GetPrivate(object));
  // Verify that this trace function is called for the object (rather than the
  // proxy object).
  DCHECK(!js::IsProxy(object));

  // The GC could run on this object before we've had a chance to set its
  // private data, so we must handle the case where JS_GetPrivate returns NULL.
  if (wrapper_private) {
    // Verify that WrapperPrivate::wrapper_proxy_'s target object is this
    // object.
    DCHECK_EQ(object,
              js::GetProxyTargetObject(wrapper_private->wrapper_proxy_));

    // The wrapper's proxy object will keep the wrapper object alive, but the
    // reverse is not true, so we must trace it explicitly.
    JS_CallObjectTracer(trace, &wrapper_private->wrapper_proxy_,
                        "WrapperPrivate::Trace");

    MozjsGlobalEnvironment* global_environment =
        MozjsGlobalEnvironment::GetFromContext(wrapper_private->context_);
    intptr_t key = ReferencedObjectMap::GetKeyForWrappable(
        wrapper_private->wrappable_.get());
    global_environment->referenced_objects()->TraceReferencedObjects(trace,
                                                                     key);
  }
}

WrapperPrivate::WrapperPrivate(
    JSContext* context, const scoped_refptr<Wrappable>& wrappable,
    JS::HandleObject wrapper_proxy,
    const GetOpaqueRootFunction& get_opaque_root_function,
    const GetReachableWrappablesFunction& get_reachable_wrappables_function)
    : context_(context),
      wrappable_(wrappable),
      wrapper_proxy_(wrapper_proxy),
      get_opaque_root_function_(get_opaque_root_function),
      get_reachable_wrappables_function_(get_reachable_wrappables_function) {
  DCHECK(js::IsProxy(wrapper_proxy));
  if (!get_opaque_root_function_.is_null() ||
      !get_reachable_wrappables_function_.is_null()) {
    MozjsGlobalEnvironment* global_environment =
        MozjsGlobalEnvironment::GetFromContext(context_);
    global_environment->opaque_root_tracker()->AddObjectWithOpaqueRoot(this);
  }
}

WrapperPrivate::~WrapperPrivate() {
  if (!get_opaque_root_function_.is_null() ||
      !get_reachable_wrappables_function_.is_null()) {
    MozjsGlobalEnvironment* global_environment =
        MozjsGlobalEnvironment::GetFromContext(context_);
    global_environment->opaque_root_tracker()->RemoveObjectWithOpaqueRoot(this);
  }
  wrapper_proxy_ = NULL;
}

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