// 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.
#ifndef COBALT_SCRIPT_MOZJS_PROXY_HANDLER_H_
#define COBALT_SCRIPT_MOZJS_PROXY_HANDLER_H_

#include <string>

#include "base/compiler_specific.h"
#include "base/logging.h"
#include "third_party/mozjs/js/src/jsapi.h"
#include "third_party/mozjs/js/src/jsproxy.h"

namespace cobalt {
namespace script {
namespace mozjs {

// SpiderMonkey has a concept of a Proxy object which is associated with another
// arbitrary object and a js::BaseProxyHandler interface. The handler interface
// provides a number of traps for providing custom implementations of
// fundamental ECMAScript operations such as getPropertyDescriptor.
//
// The implementation of each trap in the js::DirectProxyHandler class simply
// forwards each trap to the target object.
//
// In defining a JSClass a number of function pointers can be set that will
// be called when getting, setting, deleting, etc. a property, but these do not
// map well onto the Web IDL spec for implementing interfaces that support named
// and indexed properties.
//
// See third_party/mozjs/js/src/jsproxy.h for more details.
//
// ProxyHandler provides custom traps for getPropertyDescriptor, delete_, and
// enumerate to implement interfaces that support named and indexed properties.
class ProxyHandler : public js::DirectProxyHandler {
 public:
  typedef bool (*IsSupportedIndexFunction)(JSContext*, JS::HandleObject,
                                           uint32_t);
  typedef bool (*IsSupportedNameFunction)(JSContext*, JS::HandleObject,
                                          const std::string&);
  typedef void (*EnumerateSupportedIndexesFunction)(JSContext*,
                                                    JS::HandleObject,
                                                    JS::AutoIdVector*);
  typedef void (*EnumerateSupportedNamesFunction)(JSContext*, JS::HandleObject,
                                                  JS::AutoIdVector*);
  typedef bool (*IndexedDeleteFunction)(JSContext*, JS::HandleObject, uint32_t);
  typedef bool (*NamedDeleteFunction)(JSContext*, JS::HandleObject,
                                      const std::string&);

  // Hooks for interfaces that support indexed properties.
  struct IndexedPropertyHooks {
    IsSupportedIndexFunction is_supported;
    EnumerateSupportedIndexesFunction enumerate_supported;
    JSPropertyOp getter;
    JSStrictPropertyOp setter;
    IndexedDeleteFunction deleter;
  };

  // Hooks for interfaces that support named properties.
  struct NamedPropertyHooks {
    IsSupportedNameFunction is_supported;
    EnumerateSupportedNamesFunction enumerate_supported;
    JSPropertyOp getter;
    JSStrictPropertyOp setter;
    NamedDeleteFunction deleter;
  };

  static JSObject* NewProxy(JSContext* context, JSObject* object,
                            JSObject* prototype, JSObject* parent,
                            ProxyHandler* handler);

  // Construct a new ProxyHandler with the provided hooks.
  ProxyHandler(const IndexedPropertyHooks& indexed_hooks,
               const NamedPropertyHooks& named_hooks);

  // Overridden fundamental traps.
  bool getPropertyDescriptor(JSContext* context, JS::HandleObject proxy,
                             JS::HandleId id, JSPropertyDescriptor* descriptor,
                             unsigned flags) OVERRIDE;
  bool getOwnPropertyDescriptor(JSContext* context, JS::HandleObject proxy,
                                JS::HandleId id,
                                JSPropertyDescriptor* descriptor,
                                unsigned flags) OVERRIDE;
  bool delete_(JSContext* context, JS::HandleObject proxy, JS::HandleId id,
               bool* succeeded) OVERRIDE;
  bool enumerate(JSContext* context, JS::HandleObject proxy,
                 JS::AutoIdVector& properties) OVERRIDE;  // NOLINT[runtime/references]
  bool defineProperty(JSContext* context, JS::HandleObject proxy,
                      JS::HandleId id,
                      JSPropertyDescriptor* descriptor) OVERRIDE;

  // The derived traps in js::DirectProxyHandler are not implemented in terms of
  // the fundamental traps, where the traps in js::BaseProxyHandler are.
  // Redefining the derived traps to be in terms of the fundamental traps means
  // that we only need to override the fundamental traps when implementing
  // custom behavior for i.e. interfaces that support named properties.
  bool has(JSContext* context, JS::HandleObject proxy, JS::HandleId id,
           bool* bp) OVERRIDE {
    return js::BaseProxyHandler::has(context, proxy, id, bp);
  }

  bool hasOwn(JSContext* context, JS::HandleObject proxy, JS::HandleId id,
              bool* bp) OVERRIDE {
    return js::BaseProxyHandler::hasOwn(context, proxy, id, bp);
  }

  bool get(JSContext* context, JS::HandleObject proxy,
           JS::HandleObject receiver, JS::HandleId id,
           JS::MutableHandleValue vp) OVERRIDE {
    return js::BaseProxyHandler::get(context, proxy, receiver, id, vp);
  }

  bool set(JSContext* context, JS::HandleObject proxy,
           JS::HandleObject receiver, JS::HandleId id, bool strict,
           JS::MutableHandleValue vp) OVERRIDE {
    return js::BaseProxyHandler::set(context, proxy, receiver, id, strict, vp);
  }

  bool keys(JSContext* context, JS::HandleObject proxy,
            JS::AutoIdVector& props) OVERRIDE {  // NOLINT[runtime/references]
    return js::BaseProxyHandler::keys(context, proxy, props);
  }

  bool iterate(JSContext* context, JS::HandleObject proxy, unsigned flags,
               JS::MutableHandleValue vp) OVERRIDE {
    return js::BaseProxyHandler::iterate(context, proxy, flags, vp);
  }

  bool has_custom_property() const { return has_custom_property_; }

 private:
  // https://heycam.github.io/webidl/#LegacyPlatformObjectGetOwnProperty
  // This is used to support named and indexed properties.
  // Returns false on internal failure.
  bool LegacyPlatformObjectGetOwnPropertyDescriptor(
      JSContext* context, JS::HandleObject proxy, JS::HandleId id,
      JSPropertyDescriptor* descriptor);

  bool supports_named_properties() {
    return named_property_hooks_.getter != NULL;
  }

  bool supports_indexed_properties() {
    return indexed_property_hooks_.getter != NULL;
  }

  bool IsSupportedIndex(JSContext* context, JS::HandleObject object,
                        uint32_t index);

  bool IsSupportedName(JSContext* context, JS::HandleObject object,
                       const std::string& name);

  bool IsArrayIndexPropertyName(JSContext* context,
                                JS::HandleValue property_value,
                                uint32_t* out_index);

  bool IsNamedPropertyVisible(JSContext* context, JS::HandleObject object,
                              const std::string& property_name);

  IndexedPropertyHooks indexed_property_hooks_;
  NamedPropertyHooks named_property_hooks_;
  // Set to true if this object may have a custom property set on it.
  bool has_custom_property_;
};

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

#endif  // COBALT_SCRIPT_MOZJS_PROXY_HANDLER_H_
