// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "gin/wrappable.h"

#include "base/check.h"
#include "gin/arguments.h"
#include "gin/handle.h"
#include "gin/object_template_builder.h"
#include "gin/per_isolate_data.h"
#include "gin/public/isolate_holder.h"
#include "gin/test/v8_test.h"
#include "gin/try_catch.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "v8/include/v8-function.h"
#include "v8/include/v8-message.h"
#include "v8/include/v8-script.h"

namespace gin {

namespace {

// A non-member function to be bound to an ObjectTemplateBuilder.
void NonMemberMethod() {}

// This useless base class ensures that the value of a pointer to a MyObject
// (below) is not the same as the value of that pointer cast to the object's
// WrappableBase base.
class BaseClass {
 public:
  BaseClass() : value_(23) {}
  BaseClass(const BaseClass&) = delete;
  BaseClass& operator=(const BaseClass&) = delete;
  virtual ~BaseClass() = default;

  // So the compiler doesn't complain that |value_| is unused.
  int value() const { return value_; }

 private:
  int value_;
};

class MyObject : public BaseClass,
                 public Wrappable<MyObject> {
 public:
  MyObject(const MyObject&) = delete;
  MyObject& operator=(const MyObject&) = delete;

  static WrapperInfo kWrapperInfo;

  static gin::Handle<MyObject> Create(v8::Isolate* isolate) {
    return CreateHandle(isolate, new MyObject());
  }

  int value() const { return value_; }
  void set_value(int value) { value_ = value; }

  void Method() {}

 protected:
  MyObject() : value_(0) {}
  ObjectTemplateBuilder GetObjectTemplateBuilder(v8::Isolate* isolate) final {
    return Wrappable<MyObject>::GetObjectTemplateBuilder(isolate)
        .SetProperty("value", &MyObject::value, &MyObject::set_value)
        .SetMethod("memberMethod", &MyObject::Method)
        .SetMethod("nonMemberMethod", &NonMemberMethod);
  }
  ~MyObject() override = default;

 private:
  int value_;
};

class MyObject2 : public Wrappable<MyObject2> {
 public:
  static WrapperInfo kWrapperInfo;
};

class MyNamedObject : public Wrappable<MyNamedObject> {
 public:
  MyNamedObject(const MyNamedObject&) = delete;
  MyNamedObject& operator=(const MyNamedObject&) = delete;

  static WrapperInfo kWrapperInfo;

  static gin::Handle<MyNamedObject> Create(v8::Isolate* isolate) {
    return CreateHandle(isolate, new MyNamedObject());
  }

  void Method() {}

 protected:
  MyNamedObject() = default;
  ObjectTemplateBuilder GetObjectTemplateBuilder(v8::Isolate* isolate) final {
    return Wrappable<MyNamedObject>::GetObjectTemplateBuilder(isolate)
        .SetMethod("memberMethod", &MyNamedObject::Method)
        .SetMethod("nonMemberMethod", &NonMemberMethod);
  }
  const char* GetTypeName() final { return "MyNamedObject"; }
  ~MyNamedObject() override = default;
};

WrapperInfo MyObject::kWrapperInfo = { kEmbedderNativeGin };
WrapperInfo MyObject2::kWrapperInfo = { kEmbedderNativeGin };
WrapperInfo MyNamedObject::kWrapperInfo = {kEmbedderNativeGin};

}  // namespace

typedef V8Test WrappableTest;

TEST_F(WrappableTest, WrapAndUnwrap) {
  v8::Isolate* isolate = instance_->isolate();
  v8::HandleScope handle_scope(isolate);

  Handle<MyObject> obj = MyObject::Create(isolate);

  v8::Local<v8::Value> wrapper =
      ConvertToV8(isolate, obj.get()).ToLocalChecked();
  EXPECT_FALSE(wrapper.IsEmpty());

  MyObject* unwrapped = NULL;
  EXPECT_TRUE(ConvertFromV8(isolate, wrapper, &unwrapped));
  EXPECT_EQ(obj.get(), unwrapped);
}

TEST_F(WrappableTest, UnwrapFailures) {
  v8::Isolate* isolate = instance_->isolate();
  v8::HandleScope handle_scope(isolate);

  // Something that isn't an object.
  v8::Local<v8::Value> thing = v8::Number::New(isolate, 42);
  MyObject* unwrapped = NULL;
  EXPECT_FALSE(ConvertFromV8(isolate, thing, &unwrapped));
  EXPECT_FALSE(unwrapped);

  // An object that's not wrapping anything.
  thing = v8::Object::New(isolate);
  EXPECT_FALSE(ConvertFromV8(isolate, thing, &unwrapped));
  EXPECT_FALSE(unwrapped);

  // An object that's wrapping a C++ object of the wrong type.
  thing.Clear();
  thing = ConvertToV8(isolate, new MyObject2()).ToLocalChecked();
  EXPECT_FALSE(ConvertFromV8(isolate, thing, &unwrapped));
  EXPECT_FALSE(unwrapped);
}

TEST_F(WrappableTest, GetAndSetProperty) {
  v8::Isolate* isolate = instance_->isolate();
  v8::HandleScope handle_scope(isolate);

  gin::Handle<MyObject> obj = MyObject::Create(isolate);

  obj->set_value(42);
  EXPECT_EQ(42, obj->value());

  v8::Local<v8::String> source = StringToV8(isolate,
      "(function (obj) {"
      "   if (obj.value !== 42) throw 'FAIL';"
      "   else obj.value = 191; })");
  EXPECT_FALSE(source.IsEmpty());

  gin::TryCatch try_catch(isolate);
  v8::Local<v8::Script> script =
      v8::Script::Compile(context_.Get(isolate), source).ToLocalChecked();
  v8::Local<v8::Value> val =
      script->Run(context_.Get(isolate)).ToLocalChecked();
  v8::Local<v8::Function> func;
  EXPECT_TRUE(ConvertFromV8(isolate, val, &func));
  v8::Local<v8::Value> argv[] = {
      ConvertToV8(isolate, obj.get()).ToLocalChecked(),
  };
  func->Call(context_.Get(isolate), v8::Undefined(isolate), 1, argv)
      .ToLocalChecked();
  EXPECT_FALSE(try_catch.HasCaught());
  EXPECT_EQ("", try_catch.GetStackTrace());

  EXPECT_EQ(191, obj->value());
}

TEST_F(WrappableTest, MethodInvocationErrorsOnUnnamedObject) {
  v8::Isolate* isolate = instance_->isolate();
  v8::HandleScope handle_scope(isolate);
  v8::Local<v8::Context> context = context_.Get(isolate);

  gin::Handle<MyObject> obj = MyObject::Create(isolate);

  v8::Local<v8::Object> v8_object =
      ConvertToV8(isolate, obj.get()).ToLocalChecked().As<v8::Object>();
  v8::Local<v8::Value> member_method =
      v8_object->Get(context, StringToV8(isolate, "memberMethod"))
          .ToLocalChecked();
  ASSERT_TRUE(member_method->IsFunction());
  v8::Local<v8::Value> non_member_method =
      v8_object->Get(context, StringToV8(isolate, "nonMemberMethod"))
          .ToLocalChecked();
  ASSERT_TRUE(non_member_method->IsFunction());

  auto get_error = [isolate, context](v8::Local<v8::Value> function_to_run,
                                      v8::Local<v8::Value> context_object) {
    constexpr char kScript[] =
        "(function(toRun, contextObject) { toRun.apply(contextObject, []); })";
    v8::Local<v8::String> source = StringToV8(isolate, kScript);
    EXPECT_FALSE(source.IsEmpty());

    v8::TryCatch try_catch(isolate);
    v8::Local<v8::Script> script =
        v8::Script::Compile(context, source).ToLocalChecked();
    v8::Local<v8::Value> val = script->Run(context).ToLocalChecked();
    v8::Local<v8::Function> func;
    EXPECT_TRUE(ConvertFromV8(isolate, val, &func));
    v8::Local<v8::Value> argv[] = {function_to_run, context_object};
    func->Call(context, v8::Undefined(isolate), base::size(argv), argv)
        .FromMaybe(v8::Local<v8::Value>());
    if (!try_catch.HasCaught())
      return std::string();
    return V8ToString(isolate, try_catch.Message()->Get());
  };

  EXPECT_EQ(std::string(), get_error(member_method, v8_object));
  EXPECT_EQ(std::string(), get_error(non_member_method, v8_object));

  EXPECT_EQ("Uncaught TypeError: Illegal invocation",
            get_error(member_method, v8::Null(isolate)));
  // A non-member function shouldn't throw errors for being applied on a
  // null (or invalid) object.
  EXPECT_EQ(std::string(), get_error(non_member_method, v8::Null(isolate)));

  v8::Local<v8::Object> wrong_object = v8::Object::New(isolate);
  // We should get an error for passing the wrong object.
  EXPECT_EQ("Uncaught TypeError: Illegal invocation",
            get_error(member_method, wrong_object));
  // But again, not for a "static" method.
  EXPECT_EQ(std::string(), get_error(non_member_method, v8::Null(isolate)));
}

TEST_F(WrappableTest, MethodInvocationErrorsOnNamedObject) {
  v8::Isolate* isolate = instance_->isolate();
  v8::HandleScope handle_scope(isolate);
  v8::Local<v8::Context> context = context_.Get(isolate);

  gin::Handle<MyNamedObject> obj = MyNamedObject::Create(isolate);

  v8::Local<v8::Object> v8_object =
      ConvertToV8(isolate, obj.get()).ToLocalChecked().As<v8::Object>();
  v8::Local<v8::Value> member_method =
      v8_object->Get(context, StringToV8(isolate, "memberMethod"))
          .ToLocalChecked();
  ASSERT_TRUE(member_method->IsFunction());
  v8::Local<v8::Value> non_member_method =
      v8_object->Get(context, StringToV8(isolate, "nonMemberMethod"))
          .ToLocalChecked();
  ASSERT_TRUE(non_member_method->IsFunction());

  auto get_error = [isolate, context](v8::Local<v8::Value> function_to_run,
                                      v8::Local<v8::Value> context_object) {
    constexpr char kScript[] =
        "(function(toRun, contextObject) { toRun.apply(contextObject, []); })";
    v8::Local<v8::String> source = StringToV8(isolate, kScript);
    EXPECT_FALSE(source.IsEmpty());

    v8::TryCatch try_catch(isolate);
    v8::Local<v8::Script> script =
        v8::Script::Compile(context, source).ToLocalChecked();
    v8::Local<v8::Value> val = script->Run(context).ToLocalChecked();
    v8::Local<v8::Function> func;
    EXPECT_TRUE(ConvertFromV8(isolate, val, &func));
    v8::Local<v8::Value> argv[] = {function_to_run, context_object};
    func->Call(context, v8::Undefined(isolate), base::size(argv), argv)
        .FromMaybe(v8::Local<v8::Value>());
    if (!try_catch.HasCaught())
      return std::string();
    return V8ToString(isolate, try_catch.Message()->Get());
  };

  EXPECT_EQ(std::string(), get_error(member_method, v8_object));
  EXPECT_EQ(std::string(), get_error(non_member_method, v8_object));

  EXPECT_EQ(
      "Uncaught TypeError: Illegal invocation: Function must be called on "
      "an object of type MyNamedObject",
      get_error(member_method, v8::Null(isolate)));
  // A non-member function shouldn't throw errors for being applied on a
  // null (or invalid) object.
  EXPECT_EQ(std::string(), get_error(non_member_method, v8::Null(isolate)));

  v8::Local<v8::Object> wrong_object = v8::Object::New(isolate);
  // We should get an error for passing the wrong object.
  EXPECT_EQ(
      "Uncaught TypeError: Illegal invocation: Function must be called on "
      "an object of type MyNamedObject",
      get_error(member_method, wrong_object));
  // But again, not for a "static" method.
  EXPECT_EQ(std::string(), get_error(non_member_method, v8::Null(isolate)));
}

class MyObjectWithLazyProperties
    : public Wrappable<MyObjectWithLazyProperties> {
 public:
  MyObjectWithLazyProperties(const MyObjectWithLazyProperties&) = delete;
  MyObjectWithLazyProperties& operator=(const MyObjectWithLazyProperties&) =
      delete;

  static WrapperInfo kWrapperInfo;

  static gin::Handle<MyObjectWithLazyProperties> Create(v8::Isolate* isolate) {
    return CreateHandle(isolate, new MyObjectWithLazyProperties());
  }

  int access_count() const { return access_count_; }

 private:
  MyObjectWithLazyProperties() = default;

  ObjectTemplateBuilder GetObjectTemplateBuilder(v8::Isolate* isolate) final {
    return Wrappable::GetObjectTemplateBuilder(isolate)
        .SetLazyDataProperty("fortyTwo", &MyObjectWithLazyProperties::FortyTwo)
        .SetLazyDataProperty("self",
                             base::BindRepeating([](gin::Arguments* arguments) {
                               v8::Local<v8::Value> holder;
                               CHECK(arguments->GetHolder(&holder));
                               return holder;
                             }));
  }

  int FortyTwo() {
    access_count_++;
    return 42;
  }

  int access_count_ = 0;
};

WrapperInfo MyObjectWithLazyProperties::kWrapperInfo = {kEmbedderNativeGin};

TEST_F(WrappableTest, LazyPropertyGetterIsCalledOnce) {
  v8::Isolate* isolate = instance_->isolate();
  v8::HandleScope handle_scope(isolate);
  v8::Local<v8::Context> context = context_.Get(isolate);

  auto handle = MyObjectWithLazyProperties::Create(isolate);
  v8::Local<v8::Object> v8_object = handle.ToV8().As<v8::Object>();
  v8::Local<v8::String> key = StringToSymbol(isolate, "fortyTwo");
  v8::Local<v8::Value> value;

  bool has_own_property = false;
  ASSERT_TRUE(v8_object->HasOwnProperty(context, key).To(&has_own_property));
  EXPECT_TRUE(has_own_property);

  EXPECT_EQ(0, handle->access_count());

  ASSERT_TRUE(v8_object->Get(context, key).ToLocal(&value));
  EXPECT_TRUE(value->StrictEquals(v8::Int32::New(isolate, 42)));
  EXPECT_EQ(1, handle->access_count());

  ASSERT_TRUE(v8_object->Get(context, key).ToLocal(&value));
  EXPECT_TRUE(value->StrictEquals(v8::Int32::New(isolate, 42)));
  EXPECT_EQ(1, handle->access_count());
}

TEST_F(WrappableTest, LazyPropertyGetterCanBeSetFirst) {
  v8::Isolate* isolate = instance_->isolate();
  v8::HandleScope handle_scope(isolate);
  v8::Local<v8::Context> context = context_.Get(isolate);

  auto handle = MyObjectWithLazyProperties::Create(isolate);
  v8::Local<v8::Object> v8_object = handle.ToV8().As<v8::Object>();
  v8::Local<v8::String> key = StringToSymbol(isolate, "fortyTwo");
  v8::Local<v8::Value> value;

  EXPECT_EQ(0, handle->access_count());

  bool set_ok = false;
  ASSERT_TRUE(
      v8_object->Set(context, key, v8::Int32::New(isolate, 1701)).To(&set_ok));
  ASSERT_TRUE(set_ok);
  ASSERT_TRUE(v8_object->Get(context, key).ToLocal(&value));
  EXPECT_TRUE(value->StrictEquals(v8::Int32::New(isolate, 1701)));
  EXPECT_EQ(0, handle->access_count());
}

TEST_F(WrappableTest, LazyPropertyGetterCanBindSpecialArguments) {
  v8::Isolate* isolate = instance_->isolate();
  v8::HandleScope handle_scope(isolate);
  v8::Local<v8::Context> context = context_.Get(isolate);

  auto handle = MyObjectWithLazyProperties::Create(isolate);
  v8::Local<v8::Object> v8_object = handle.ToV8().As<v8::Object>();
  v8::Local<v8::Value> value;
  ASSERT_TRUE(
      v8_object->Get(context, StringToSymbol(isolate, "self")).ToLocal(&value));
  EXPECT_TRUE(v8_object == value);
}

}  // namespace gin
