// 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_45_MOZJS_GLOBAL_ENVIRONMENT_H_
#define COBALT_SCRIPT_MOZJS_45_MOZJS_GLOBAL_ENVIRONMENT_H_

#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

#include "base/hash_tables.h"
#include "base/logging.h"
#include "base/optional.h"
#include "base/stl_util.h"
#include "base/threading/thread_checker.h"
#include "cobalt/script/global_environment.h"
#include "cobalt/script/javascript_engine.h"
#include "cobalt/script/mozjs-45/interface_data.h"
#include "cobalt/script/mozjs-45/util/exception_helpers.h"
#include "cobalt/script/mozjs-45/weak_heap_object_manager.h"
#include "cobalt/script/mozjs-45/wrapper_factory.h"
#include "third_party/mozjs-45/js/public/Proxy.h"
#include "third_party/mozjs-45/js/src/jsapi.h"
#include "third_party/mozjs-45/js/src/proxy/Proxy.h"

namespace cobalt {
namespace script {
namespace mozjs {

class MozjsScriptValueFactory;
class ReferencedObjectMap;
class WeakHandle;

// Manages a handle to a JavaScript engine's global object. The lifetime of
// the global object is not necessarily tied to the lifetime of the proxy.
class MozjsGlobalEnvironment : public GlobalEnvironment,
                               public Wrappable::CachedWrapperAccessor {
 public:
  static MozjsGlobalEnvironment* GetFromContext(JSContext* context);

  // This will be called every time an attempt is made to use eval() and
  // friends. If it returns false, then the ReportErrorHandler will be fired
  // with an error that eval() is disabled.
  static bool CheckEval(JSContext* context);

  explicit MozjsGlobalEnvironment(JSRuntime* runtime);
  ~MozjsGlobalEnvironment() override;

  void CreateGlobalObject() override;
  // |script::GlobalEnvironment| will dispatch to this implementation in the
  // create_global_object_impl block of the bindings interface template.
  template <typename GlobalInterface>
  void CreateGlobalObject(
      const scoped_refptr<GlobalInterface>& global_interface,
      EnvironmentSettings* environment_settings);

  bool EvaluateScript(const scoped_refptr<SourceCode>& script,
                      std::string* out_result_utf8) override;

  bool EvaluateScript(
      const scoped_refptr<SourceCode>& script_utf8,
      const scoped_refptr<Wrappable>& owning_object,
      base::optional<ValueHandleHolder::Reference>* out_value_handle) override;

  std::vector<StackFrame> GetStackTrace(int max_frames) override;
  using GlobalEnvironment::GetStackTrace;

  void PreventGarbageCollection(
      const scoped_refptr<Wrappable>& wrappable) override;

  void AllowGarbageCollection(
      const scoped_refptr<Wrappable>& wrappable) override;

  void AddRoot(Traceable* traceable) override;

  void RemoveRoot(Traceable* traceable) override;

  void DisableEval(const std::string& message) override;

  void EnableEval() override;

  void DisableJit() override;

  void SetReportEvalCallback(const base::Closure& report_eval) override;

  void SetReportErrorCallback(
      const ReportErrorCallback& report_error_callback) override;

  void Bind(const std::string& identifier,
            const scoped_refptr<Wrappable>& impl) override;

  ScriptValueFactory* script_value_factory() override;

  JSContext* context() const { return context_; }

  JSObject* global_object_proxy() const { return global_object_proxy_; }
  JSObject* global_object() const {
    return js::GetProxyTargetObject(global_object_proxy_);
  }

  WrapperFactory* wrapper_factory() { return wrapper_factory_.get(); }

  ReferencedObjectMap* referenced_objects() {
    return referenced_objects_.get();
  }

  WeakHeapObjectManager* weak_object_manager() { return &weak_object_manager_; }

  base::hash_set<Traceable*>* visited_traceables() {
    return &visited_traceables_;
  }

  EnvironmentSettings* GetEnvironmentSettings() const {
    return environment_settings_;
  }

  void GetStoredPromiseConstructor(
      JS::MutableHandleObject out_promise_constructor) {
    DCHECK(stored_promise_constructor_);
    out_promise_constructor.set(*stored_promise_constructor_);
    DCHECK(out_promise_constructor);
  }

  void SetGlobalObjectProxyAndWrapper(
      JS::HandleObject global_object_proxy,
      const scoped_refptr<Wrappable>& wrappable);

  // Any tracked InterfaceData will have it's GC handles visited and marked as
  // roots.  |key| is the interface's unique id, which is generated during
  // bindings idl compilation.
  InterfaceData* GetInterfaceData(int key);

  // This will be called during garbage collection after GC objects have been
  // marked, but before they have been finalized. This allows an opportunity to
  // sweep away references to GC objects that will be deleted.
  void DoSweep();

  void BeginGarbageCollection();
  void EndGarbageCollection();

  void ReportError(const char* message, JSErrorReport* report);

 private:
  // Helper struct to ensure the context is destroyed in the correct order
  // relative to the MozjsGlobalEnvironment's other members.
  struct ContextDestructor {
    explicit ContextDestructor(JSContext** context) : context(context) {}
    ~ContextDestructor() { JS_DestroyContext(*context); }
    JSContext** const context;
  };

  struct CountedHeapObject {
    CountedHeapObject(const JS::Heap<JSObject*>& heap_object, int count)
        : heap_object(heap_object), count(count) {}
    JS::Heap<JSObject*> heap_object;
    int count;
  };

  static void TraceFunction(JSTracer* trace, void* data);

  // Evaluates any automatically included JavaScript for the environment.
  void EvaluateAutomatics();

  bool EvaluateScriptInternal(const scoped_refptr<SourceCode>& source_code,
                              JS::MutableHandleValue out_result);

  void EvaluateEmbeddedScript(const unsigned char* data, size_t size,
                              const char* filename);

  base::ThreadChecker thread_checker_;
  JSContext* context_;
  int garbage_collection_count_;
  WeakHeapObjectManager weak_object_manager_;
  std::unordered_map<Wrappable*, CountedHeapObject> kept_alive_objects_;
  scoped_ptr<ReferencedObjectMap> referenced_objects_;
  std::vector<InterfaceData> cached_interface_data_;

  ContextDestructor context_destructor_;
  scoped_ptr<WrapperFactory> wrapper_factory_;
  scoped_ptr<MozjsScriptValueFactory> script_value_factory_;
  JS::Heap<JSObject*> global_object_proxy_;
  EnvironmentSettings* environment_settings_;
  // TODO: Should be |std::unordered_set| once C++11 is enabled.
  base::hash_set<Traceable*> visited_traceables_;
  std::unordered_multiset<Traceable*> roots_;

  // Store the result of "Promise" immediately after evaluating the
  // promise polyfill in order to defend against application JavaScript
  // changing it to something else later.  Note that this should be removed if
  // we ever rebase to a SpiderMonkey version >= 50, as that is when native
  // promises were added to it.
  base::optional<JS::PersistentRootedObject> stored_promise_constructor_;

  // If non-NULL, the error message from the ReportErrorHandler will get
  // assigned to this instead of being printed.
  std::string* last_error_message_;

  bool eval_enabled_;
  base::optional<std::string> eval_disabled_message_;
  base::Closure report_eval_;
  ReportErrorCallback report_error_callback_;

  friend class GlobalObjectProxy;
};

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

#endif  // COBALT_SCRIPT_MOZJS_45_MOZJS_GLOBAL_ENVIRONMENT_H_
