// Copyright 2015 the V8 project 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 "src/wasm/wasm-js.h"

#include <cinttypes>
#include <cstring>

#include "src/api/api-inl.h"
#include "src/api/api-natives.h"
#include "src/ast/ast.h"
#include "src/base/logging.h"
#include "src/base/overflowing-math.h"
#include "src/common/assert-scope.h"
#include "src/execution/execution.h"
#include "src/execution/frames-inl.h"
#include "src/execution/isolate.h"
#include "src/handles/handles.h"
#include "src/heap/factory.h"
#include "src/init/v8.h"
#include "src/objects/js-collection-inl.h"
#include "src/objects/js-promise-inl.h"
#include "src/objects/objects-inl.h"
#include "src/objects/templates.h"
#include "src/parsing/parse-info.h"
#include "src/tasks/task-utils.h"
#include "src/trap-handler/trap-handler.h"
#include "src/wasm/function-compiler.h"
#include "src/wasm/streaming-decoder.h"
#include "src/wasm/value-type.h"
#include "src/wasm/wasm-debug.h"
#include "src/wasm/wasm-engine.h"
#include "src/wasm/wasm-limits.h"
#include "src/wasm/wasm-objects-inl.h"
#include "src/wasm/wasm-serialization.h"
#include "src/wasm/wasm-value.h"

using v8::internal::wasm::ErrorThrower;
using v8::internal::wasm::ScheduledErrorThrower;

namespace v8 {

class WasmStreaming::WasmStreamingImpl {
 public:
  WasmStreamingImpl(
      Isolate* isolate, const char* api_method_name,
      std::shared_ptr<internal::wasm::CompilationResultResolver> resolver)
      : isolate_(isolate), resolver_(std::move(resolver)) {
    i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate_);
    auto enabled_features = i::wasm::WasmFeatures::FromIsolate(i_isolate);
    streaming_decoder_ = i_isolate->wasm_engine()->StartStreamingCompilation(
        i_isolate, enabled_features, handle(i_isolate->context(), i_isolate),
        api_method_name, resolver_);
  }

  void OnBytesReceived(const uint8_t* bytes, size_t size) {
    streaming_decoder_->OnBytesReceived(i::VectorOf(bytes, size));
  }
  void Finish() { streaming_decoder_->Finish(); }

  void Abort(MaybeLocal<Value> exception) {
    i::HandleScope scope(reinterpret_cast<i::Isolate*>(isolate_));
    streaming_decoder_->Abort();

    // If no exception value is provided, we do not reject the promise. This can
    // happen when streaming compilation gets aborted when no script execution
    // is allowed anymore, e.g. when a browser tab gets refreshed.
    if (exception.IsEmpty()) return;

    resolver_->OnCompilationFailed(
        Utils::OpenHandle(*exception.ToLocalChecked()));
  }

  bool SetCompiledModuleBytes(const uint8_t* bytes, size_t size) {
    if (!i::wasm::IsSupportedVersion({bytes, size})) return false;
    return streaming_decoder_->SetCompiledModuleBytes({bytes, size});
  }

  void SetClient(std::shared_ptr<Client> client) {
    streaming_decoder_->SetModuleCompiledCallback(
        [client, streaming_decoder = streaming_decoder_](
            const std::shared_ptr<i::wasm::NativeModule>& native_module) {
          i::Vector<const char> url = streaming_decoder->url();
          auto compiled_wasm_module =
              CompiledWasmModule(native_module, url.begin(), url.size());
          client->OnModuleCompiled(compiled_wasm_module);
        });
  }

  void SetUrl(internal::Vector<const char> url) {
    streaming_decoder_->SetUrl(url);
  }

 private:
  Isolate* const isolate_;
  std::shared_ptr<internal::wasm::StreamingDecoder> streaming_decoder_;
  std::shared_ptr<internal::wasm::CompilationResultResolver> resolver_;
};

WasmStreaming::WasmStreaming(std::unique_ptr<WasmStreamingImpl> impl)
    : impl_(std::move(impl)) {
  TRACE_EVENT0("v8.wasm", "wasm.InitializeStreaming");
}

// The destructor is defined here because we have a unique_ptr with forward
// declaration.
WasmStreaming::~WasmStreaming() = default;

void WasmStreaming::OnBytesReceived(const uint8_t* bytes, size_t size) {
  TRACE_EVENT1("v8.wasm", "wasm.OnBytesReceived", "bytes", size);
  impl_->OnBytesReceived(bytes, size);
}

void WasmStreaming::Finish() {
  TRACE_EVENT0("v8.wasm", "wasm.FinishStreaming");
  impl_->Finish();
}

void WasmStreaming::Abort(MaybeLocal<Value> exception) {
  TRACE_EVENT0("v8.wasm", "wasm.AbortStreaming");
  impl_->Abort(exception);
}

bool WasmStreaming::SetCompiledModuleBytes(const uint8_t* bytes, size_t size) {
  TRACE_EVENT0("v8.wasm", "wasm.SetCompiledModuleBytes");
  return impl_->SetCompiledModuleBytes(bytes, size);
}

void WasmStreaming::SetClient(std::shared_ptr<Client> client) {
  TRACE_EVENT0("v8.wasm", "wasm.WasmStreaming.SetClient");
  impl_->SetClient(client);
}

void WasmStreaming::SetUrl(const char* url, size_t length) {
  TRACE_EVENT0("v8.wasm", "wasm.SetUrl");
  impl_->SetUrl(internal::VectorOf(url, length));
}

// static
std::shared_ptr<WasmStreaming> WasmStreaming::Unpack(Isolate* isolate,
                                                     Local<Value> value) {
  TRACE_EVENT0("v8.wasm", "wasm.WasmStreaming.Unpack");
  i::HandleScope scope(reinterpret_cast<i::Isolate*>(isolate));
  auto managed =
      i::Handle<i::Managed<WasmStreaming>>::cast(Utils::OpenHandle(*value));
  return managed->get();
}

namespace {

#define ASSIGN(type, var, expr)                      \
  Local<type> var;                                   \
  do {                                               \
    if (!expr.ToLocal(&var)) {                       \
      DCHECK(i_isolate->has_scheduled_exception());  \
      return;                                        \
    } else {                                         \
      DCHECK(!i_isolate->has_scheduled_exception()); \
    }                                                \
  } while (false)

i::Handle<i::String> v8_str(i::Isolate* isolate, const char* str) {
  return isolate->factory()->NewStringFromAsciiChecked(str);
}
Local<String> v8_str(Isolate* isolate, const char* str) {
  return Utils::ToLocal(v8_str(reinterpret_cast<i::Isolate*>(isolate), str));
}

#define GET_FIRST_ARGUMENT_AS(Type)                                  \
  i::MaybeHandle<i::Wasm##Type##Object> GetFirstArgumentAs##Type(    \
      const v8::FunctionCallbackInfo<v8::Value>& args,               \
      ErrorThrower* thrower) {                                       \
    i::Handle<i::Object> arg0 = Utils::OpenHandle(*args[0]);         \
    if (!arg0->IsWasm##Type##Object()) {                             \
      thrower->TypeError("Argument 0 must be a WebAssembly." #Type); \
      return {};                                                     \
    }                                                                \
    Local<Object> obj = Local<Object>::Cast(args[0]);                \
    return i::Handle<i::Wasm##Type##Object>::cast(                   \
        v8::Utils::OpenHandle(*obj));                                \
  }

GET_FIRST_ARGUMENT_AS(Module)
GET_FIRST_ARGUMENT_AS(Memory)
GET_FIRST_ARGUMENT_AS(Table)
GET_FIRST_ARGUMENT_AS(Global)

#undef GET_FIRST_ARGUMENT_AS

i::wasm::ModuleWireBytes GetFirstArgumentAsBytes(
    const v8::FunctionCallbackInfo<v8::Value>& args, ErrorThrower* thrower,
    bool* is_shared) {
  const uint8_t* start = nullptr;
  size_t length = 0;
  v8::Local<v8::Value> source = args[0];
  if (source->IsArrayBuffer()) {
    // A raw array buffer was passed.
    Local<ArrayBuffer> buffer = Local<ArrayBuffer>::Cast(source);
    auto backing_store = buffer->GetBackingStore();

    start = reinterpret_cast<const uint8_t*>(backing_store->Data());
    length = backing_store->ByteLength();
    *is_shared = buffer->IsSharedArrayBuffer();
  } else if (source->IsTypedArray()) {
    // A TypedArray was passed.
    Local<TypedArray> array = Local<TypedArray>::Cast(source);
    Local<ArrayBuffer> buffer = array->Buffer();

    auto backing_store = buffer->GetBackingStore();

    start = reinterpret_cast<const uint8_t*>(backing_store->Data()) +
            array->ByteOffset();
    length = array->ByteLength();
    *is_shared = buffer->IsSharedArrayBuffer();
  } else {
    thrower->TypeError("Argument 0 must be a buffer source");
  }
  DCHECK_IMPLIES(length, start != nullptr);
  if (length == 0) {
    thrower->CompileError("BufferSource argument is empty");
  }
  size_t max_length = i::wasm::max_module_size();
  if (length > max_length) {
    thrower->RangeError("buffer source exceeds maximum size of %zu (is %zu)",
                        max_length, length);
  }
  if (thrower->error()) return i::wasm::ModuleWireBytes(nullptr, nullptr);
  return i::wasm::ModuleWireBytes(start, start + length);
}

i::MaybeHandle<i::JSReceiver> GetValueAsImports(Local<Value> arg,
                                                ErrorThrower* thrower) {
  if (arg->IsUndefined()) return {};

  if (!arg->IsObject()) {
    thrower->TypeError("Argument 1 must be an object");
    return {};
  }
  Local<Object> obj = Local<Object>::Cast(arg);
  return i::Handle<i::JSReceiver>::cast(v8::Utils::OpenHandle(*obj));
}

namespace {
// This class resolves the result of WebAssembly.compile. It just places the
// compilation result in the supplied {promise}.
class AsyncCompilationResolver : public i::wasm::CompilationResultResolver {
 public:
  AsyncCompilationResolver(i::Isolate* isolate, i::Handle<i::JSPromise> promise)
      : promise_(isolate->global_handles()->Create(*promise)) {
    i::GlobalHandles::AnnotateStrongRetainer(promise_.location(),
                                             kGlobalPromiseHandle);
  }

  ~AsyncCompilationResolver() override {
    i::GlobalHandles::Destroy(promise_.location());
  }

  void OnCompilationSucceeded(i::Handle<i::WasmModuleObject> result) override {
    if (finished_) return;
    finished_ = true;
    i::MaybeHandle<i::Object> promise_result =
        i::JSPromise::Resolve(promise_, result);
    CHECK_EQ(promise_result.is_null(),
             promise_->GetIsolate()->has_pending_exception());
  }

  void OnCompilationFailed(i::Handle<i::Object> error_reason) override {
    if (finished_) return;
    finished_ = true;
    i::MaybeHandle<i::Object> promise_result =
        i::JSPromise::Reject(promise_, error_reason);
    CHECK_EQ(promise_result.is_null(),
             promise_->GetIsolate()->has_pending_exception());
  }

 private:
  static constexpr char kGlobalPromiseHandle[] =
      "AsyncCompilationResolver::promise_";
  bool finished_ = false;
  i::Handle<i::JSPromise> promise_;
};

constexpr char AsyncCompilationResolver::kGlobalPromiseHandle[];

// This class resolves the result of WebAssembly.instantiate(module, imports).
// It just places the instantiation result in the supplied {promise}.
class InstantiateModuleResultResolver
    : public i::wasm::InstantiationResultResolver {
 public:
  InstantiateModuleResultResolver(i::Isolate* isolate,
                                  i::Handle<i::JSPromise> promise)
      : promise_(isolate->global_handles()->Create(*promise)) {
    i::GlobalHandles::AnnotateStrongRetainer(promise_.location(),
                                             kGlobalPromiseHandle);
  }

  ~InstantiateModuleResultResolver() override {
    i::GlobalHandles::Destroy(promise_.location());
  }

  void OnInstantiationSucceeded(
      i::Handle<i::WasmInstanceObject> instance) override {
    i::MaybeHandle<i::Object> promise_result =
        i::JSPromise::Resolve(promise_, instance);
    CHECK_EQ(promise_result.is_null(),
             promise_->GetIsolate()->has_pending_exception());
  }

  void OnInstantiationFailed(i::Handle<i::Object> error_reason) override {
    i::MaybeHandle<i::Object> promise_result =
        i::JSPromise::Reject(promise_, error_reason);
    CHECK_EQ(promise_result.is_null(),
             promise_->GetIsolate()->has_pending_exception());
  }

 private:
  static constexpr char kGlobalPromiseHandle[] =
      "InstantiateModuleResultResolver::promise_";
  i::Handle<i::JSPromise> promise_;
};

constexpr char InstantiateModuleResultResolver::kGlobalPromiseHandle[];

// This class resolves the result of WebAssembly.instantiate(bytes, imports).
// For that it creates a new {JSObject} which contains both the provided
// {WasmModuleObject} and the resulting {WebAssemblyInstanceObject} itself.
class InstantiateBytesResultResolver
    : public i::wasm::InstantiationResultResolver {
 public:
  InstantiateBytesResultResolver(i::Isolate* isolate,
                                 i::Handle<i::JSPromise> promise,
                                 i::Handle<i::WasmModuleObject> module)
      : isolate_(isolate),
        promise_(isolate_->global_handles()->Create(*promise)),
        module_(isolate_->global_handles()->Create(*module)) {
    i::GlobalHandles::AnnotateStrongRetainer(promise_.location(),
                                             kGlobalPromiseHandle);
    i::GlobalHandles::AnnotateStrongRetainer(module_.location(),
                                             kGlobalModuleHandle);
  }

  ~InstantiateBytesResultResolver() override {
    i::GlobalHandles::Destroy(promise_.location());
    i::GlobalHandles::Destroy(module_.location());
  }

  void OnInstantiationSucceeded(
      i::Handle<i::WasmInstanceObject> instance) override {
    // The result is a JSObject with 2 fields which contain the
    // WasmInstanceObject and the WasmModuleObject.
    i::Handle<i::JSObject> result =
        isolate_->factory()->NewJSObject(isolate_->object_function());

    i::Handle<i::String> instance_name =
        isolate_->factory()->NewStringFromStaticChars("instance");

    i::Handle<i::String> module_name =
        isolate_->factory()->NewStringFromStaticChars("module");

    i::JSObject::AddProperty(isolate_, result, instance_name, instance,
                             i::NONE);
    i::JSObject::AddProperty(isolate_, result, module_name, module_, i::NONE);

    i::MaybeHandle<i::Object> promise_result =
        i::JSPromise::Resolve(promise_, result);
    CHECK_EQ(promise_result.is_null(), isolate_->has_pending_exception());
  }

  void OnInstantiationFailed(i::Handle<i::Object> error_reason) override {
    i::MaybeHandle<i::Object> promise_result =
        i::JSPromise::Reject(promise_, error_reason);
    CHECK_EQ(promise_result.is_null(), isolate_->has_pending_exception());
  }

 private:
  static constexpr char kGlobalPromiseHandle[] =
      "InstantiateBytesResultResolver::promise_";
  static constexpr char kGlobalModuleHandle[] =
      "InstantiateBytesResultResolver::module_";
  i::Isolate* isolate_;
  i::Handle<i::JSPromise> promise_;
  i::Handle<i::WasmModuleObject> module_;
};

constexpr char InstantiateBytesResultResolver::kGlobalPromiseHandle[];
constexpr char InstantiateBytesResultResolver::kGlobalModuleHandle[];

// This class is the {CompilationResultResolver} for
// WebAssembly.instantiate(bytes, imports). When compilation finishes,
// {AsyncInstantiate} is started on the compilation result.
class AsyncInstantiateCompileResultResolver
    : public i::wasm::CompilationResultResolver {
 public:
  AsyncInstantiateCompileResultResolver(
      i::Isolate* isolate, i::Handle<i::JSPromise> promise,
      i::MaybeHandle<i::JSReceiver> maybe_imports)
      : isolate_(isolate),
        promise_(isolate_->global_handles()->Create(*promise)),
        maybe_imports_(maybe_imports.is_null()
                           ? maybe_imports
                           : isolate_->global_handles()->Create(
                                 *maybe_imports.ToHandleChecked())) {
    i::GlobalHandles::AnnotateStrongRetainer(promise_.location(),
                                             kGlobalPromiseHandle);
    if (!maybe_imports_.is_null()) {
      i::GlobalHandles::AnnotateStrongRetainer(
          maybe_imports_.ToHandleChecked().location(), kGlobalImportsHandle);
    }
  }

  ~AsyncInstantiateCompileResultResolver() override {
    i::GlobalHandles::Destroy(promise_.location());
    if (!maybe_imports_.is_null()) {
      i::GlobalHandles::Destroy(maybe_imports_.ToHandleChecked().location());
    }
  }

  void OnCompilationSucceeded(i::Handle<i::WasmModuleObject> result) override {
    if (finished_) return;
    finished_ = true;
    isolate_->wasm_engine()->AsyncInstantiate(
        isolate_,
        std::make_unique<InstantiateBytesResultResolver>(isolate_, promise_,
                                                         result),
        result, maybe_imports_);
  }

  void OnCompilationFailed(i::Handle<i::Object> error_reason) override {
    if (finished_) return;
    finished_ = true;
    i::MaybeHandle<i::Object> promise_result =
        i::JSPromise::Reject(promise_, error_reason);
    CHECK_EQ(promise_result.is_null(), isolate_->has_pending_exception());
  }

 private:
  static constexpr char kGlobalPromiseHandle[] =
      "AsyncInstantiateCompileResultResolver::promise_";
  static constexpr char kGlobalImportsHandle[] =
      "AsyncInstantiateCompileResultResolver::module_";
  bool finished_ = false;
  i::Isolate* isolate_;
  i::Handle<i::JSPromise> promise_;
  i::MaybeHandle<i::JSReceiver> maybe_imports_;
};

constexpr char AsyncInstantiateCompileResultResolver::kGlobalPromiseHandle[];
constexpr char AsyncInstantiateCompileResultResolver::kGlobalImportsHandle[];

std::string ToString(const char* name) { return std::string(name); }

std::string ToString(const i::Handle<i::String> name) {
  return std::string("Property '") + name->ToCString().get() + "'";
}

// Web IDL: '[EnforceRange] unsigned long'
// Previously called ToNonWrappingUint32 in the draft WebAssembly JS spec.
// https://heycam.github.io/webidl/#EnforceRange
template <typename T>
bool EnforceUint32(T argument_name, Local<v8::Value> v, Local<Context> context,
                   ErrorThrower* thrower, uint32_t* res) {
  double double_number;

  if (!v->NumberValue(context).To(&double_number)) {
    thrower->TypeError("%s must be convertible to a number",
                       ToString(argument_name).c_str());
    return false;
  }
  if (!std::isfinite(double_number)) {
    thrower->TypeError("%s must be convertible to a valid number",
                       ToString(argument_name).c_str());
    return false;
  }
  if (double_number < 0) {
    thrower->TypeError("%s must be non-negative",
                       ToString(argument_name).c_str());
    return false;
  }
  if (double_number > std::numeric_limits<uint32_t>::max()) {
    thrower->TypeError("%s must be in the unsigned long range",
                       ToString(argument_name).c_str());
    return false;
  }

  *res = static_cast<uint32_t>(double_number);
  return true;
}
}  // namespace

// WebAssembly.compile(bytes) -> Promise
void WebAssemblyCompile(const v8::FunctionCallbackInfo<v8::Value>& args) {
  constexpr const char* kAPIMethodName = "WebAssembly.compile()";
  v8::Isolate* isolate = args.GetIsolate();
  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);

  HandleScope scope(isolate);
  ScheduledErrorThrower thrower(i_isolate, kAPIMethodName);

  if (!i::wasm::IsWasmCodegenAllowed(i_isolate, i_isolate->native_context())) {
    thrower.CompileError("Wasm code generation disallowed by embedder");
  }

  Local<Context> context = isolate->GetCurrentContext();
  ASSIGN(Promise::Resolver, promise_resolver, Promise::Resolver::New(context));
  Local<Promise> promise = promise_resolver->GetPromise();
  v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
  return_value.Set(promise);

  std::shared_ptr<i::wasm::CompilationResultResolver> resolver(
      new AsyncCompilationResolver(i_isolate, Utils::OpenHandle(*promise)));

  bool is_shared = false;
  auto bytes = GetFirstArgumentAsBytes(args, &thrower, &is_shared);
  if (thrower.error()) {
    resolver->OnCompilationFailed(thrower.Reify());
    return;
  }
  // Asynchronous compilation handles copying wire bytes if necessary.
  auto enabled_features = i::wasm::WasmFeatures::FromIsolate(i_isolate);
  i_isolate->wasm_engine()->AsyncCompile(i_isolate, enabled_features,
                                         std::move(resolver), bytes, is_shared,
                                         kAPIMethodName);
}

void WasmStreamingCallbackForTesting(
    const v8::FunctionCallbackInfo<v8::Value>& args) {
  v8::Isolate* isolate = args.GetIsolate();
  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);

  HandleScope scope(isolate);
  ScheduledErrorThrower thrower(i_isolate, "WebAssembly.compile()");

  std::shared_ptr<v8::WasmStreaming> streaming =
      v8::WasmStreaming::Unpack(args.GetIsolate(), args.Data());

  bool is_shared = false;
  i::wasm::ModuleWireBytes bytes =
      GetFirstArgumentAsBytes(args, &thrower, &is_shared);
  if (thrower.error()) {
    streaming->Abort(Utils::ToLocal(thrower.Reify()));
    return;
  }
  streaming->OnBytesReceived(bytes.start(), bytes.length());
  streaming->Finish();
  CHECK(!thrower.error());
}

void WasmStreamingPromiseFailedCallback(
    const v8::FunctionCallbackInfo<v8::Value>& args) {
  std::shared_ptr<v8::WasmStreaming> streaming =
      v8::WasmStreaming::Unpack(args.GetIsolate(), args.Data());
  streaming->Abort(args[0]);
}

// WebAssembly.compileStreaming(Response | Promise<Response>)
//   -> Promise<WebAssembly.Module>
void WebAssemblyCompileStreaming(
    const v8::FunctionCallbackInfo<v8::Value>& args) {
  v8::Isolate* isolate = args.GetIsolate();
  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
  HandleScope scope(isolate);
  const char* const kAPIMethodName = "WebAssembly.compileStreaming()";
  ScheduledErrorThrower thrower(i_isolate, kAPIMethodName);
  Local<Context> context = isolate->GetCurrentContext();

  // Create and assign the return value of this function.
  ASSIGN(Promise::Resolver, result_resolver, Promise::Resolver::New(context));
  Local<Promise> promise = result_resolver->GetPromise();
  v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
  return_value.Set(promise);

  // Prepare the CompilationResultResolver for the compilation.
  auto resolver = std::make_shared<AsyncCompilationResolver>(
      i_isolate, Utils::OpenHandle(*promise));

  if (!i::wasm::IsWasmCodegenAllowed(i_isolate, i_isolate->native_context())) {
    thrower.CompileError("Wasm code generation disallowed by embedder");
    resolver->OnCompilationFailed(thrower.Reify());
    return;
  }

  // Allocate the streaming decoder in a Managed so we can pass it to the
  // embedder.
  i::Handle<i::Managed<WasmStreaming>> data =
      i::Managed<WasmStreaming>::Allocate(
          i_isolate, 0,
          std::make_unique<WasmStreaming::WasmStreamingImpl>(
              isolate, kAPIMethodName, resolver));

  DCHECK_NOT_NULL(i_isolate->wasm_streaming_callback());
  ASSIGN(
      v8::Function, compile_callback,
      v8::Function::New(context, i_isolate->wasm_streaming_callback(),
                        Utils::ToLocal(i::Handle<i::Object>::cast(data)), 1));
  ASSIGN(
      v8::Function, reject_callback,
      v8::Function::New(context, WasmStreamingPromiseFailedCallback,
                        Utils::ToLocal(i::Handle<i::Object>::cast(data)), 1));

  // The parameter may be of type {Response} or of type {Promise<Response>}.
  // Treat either case of parameter as Promise.resolve(parameter)
  // as per https://www.w3.org/2001/tag/doc/promises-guide#resolve-arguments

  // Ending with:
  //    return Promise.resolve(parameter).then(compile_callback);
  ASSIGN(Promise::Resolver, input_resolver, Promise::Resolver::New(context));
  if (!input_resolver->Resolve(context, args[0]).IsJust()) return;

  // We do not have any use of the result here. The {compile_callback} will
  // start streaming compilation, which will eventually resolve the promise we
  // set as result value.
  USE(input_resolver->GetPromise()->Then(context, compile_callback,
                                         reject_callback));
}

// WebAssembly.validate(bytes) -> bool
void WebAssemblyValidate(const v8::FunctionCallbackInfo<v8::Value>& args) {
  v8::Isolate* isolate = args.GetIsolate();
  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
  HandleScope scope(isolate);
  ScheduledErrorThrower thrower(i_isolate, "WebAssembly.validate()");

  bool is_shared = false;
  auto bytes = GetFirstArgumentAsBytes(args, &thrower, &is_shared);

  v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();

  if (thrower.error()) {
    if (thrower.wasm_error()) thrower.Reset();  // Clear error.
    return_value.Set(v8::False(isolate));
    return;
  }

  auto enabled_features = i::wasm::WasmFeatures::FromIsolate(i_isolate);
  bool validated = false;
  if (is_shared) {
    // Make a copy of the wire bytes to avoid concurrent modification.
    std::unique_ptr<uint8_t[]> copy(new uint8_t[bytes.length()]);
    memcpy(copy.get(), bytes.start(), bytes.length());
    i::wasm::ModuleWireBytes bytes_copy(copy.get(),
                                        copy.get() + bytes.length());
    validated = i_isolate->wasm_engine()->SyncValidate(
        i_isolate, enabled_features, bytes_copy);
  } else {
    // The wire bytes are not shared, OK to use them directly.
    validated = i_isolate->wasm_engine()->SyncValidate(i_isolate,
                                                       enabled_features, bytes);
  }

  return_value.Set(Boolean::New(isolate, validated));
}

// new WebAssembly.Module(bytes) -> WebAssembly.Module
void WebAssemblyModule(const v8::FunctionCallbackInfo<v8::Value>& args) {
  v8::Isolate* isolate = args.GetIsolate();
  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
  if (i_isolate->wasm_module_callback()(args)) return;

  HandleScope scope(isolate);
  ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Module()");

  if (!args.IsConstructCall()) {
    thrower.TypeError("WebAssembly.Module must be invoked with 'new'");
    return;
  }
  if (!i::wasm::IsWasmCodegenAllowed(i_isolate, i_isolate->native_context())) {
    thrower.CompileError("Wasm code generation disallowed by embedder");
    return;
  }

  bool is_shared = false;
  auto bytes = GetFirstArgumentAsBytes(args, &thrower, &is_shared);

  if (thrower.error()) {
    return;
  }
  auto enabled_features = i::wasm::WasmFeatures::FromIsolate(i_isolate);
  i::MaybeHandle<i::Object> module_obj;
  if (is_shared) {
    // Make a copy of the wire bytes to avoid concurrent modification.
    std::unique_ptr<uint8_t[]> copy(new uint8_t[bytes.length()]);
    memcpy(copy.get(), bytes.start(), bytes.length());
    i::wasm::ModuleWireBytes bytes_copy(copy.get(),
                                        copy.get() + bytes.length());
    module_obj = i_isolate->wasm_engine()->SyncCompile(
        i_isolate, enabled_features, &thrower, bytes_copy);
  } else {
    // The wire bytes are not shared, OK to use them directly.
    module_obj = i_isolate->wasm_engine()->SyncCompile(
        i_isolate, enabled_features, &thrower, bytes);
  }

  if (module_obj.is_null()) return;

  v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
  return_value.Set(Utils::ToLocal(module_obj.ToHandleChecked()));
}

// WebAssembly.Module.imports(module) -> Array<Import>
void WebAssemblyModuleImports(const v8::FunctionCallbackInfo<v8::Value>& args) {
  HandleScope scope(args.GetIsolate());
  v8::Isolate* isolate = args.GetIsolate();
  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
  ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Module.imports()");

  auto maybe_module = GetFirstArgumentAsModule(args, &thrower);
  if (thrower.error()) return;
  auto imports = i::wasm::GetImports(i_isolate, maybe_module.ToHandleChecked());
  args.GetReturnValue().Set(Utils::ToLocal(imports));
}

// WebAssembly.Module.exports(module) -> Array<Export>
void WebAssemblyModuleExports(const v8::FunctionCallbackInfo<v8::Value>& args) {
  HandleScope scope(args.GetIsolate());
  v8::Isolate* isolate = args.GetIsolate();
  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
  ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Module.exports()");

  auto maybe_module = GetFirstArgumentAsModule(args, &thrower);
  if (thrower.error()) return;
  auto exports = i::wasm::GetExports(i_isolate, maybe_module.ToHandleChecked());
  args.GetReturnValue().Set(Utils::ToLocal(exports));
}

// WebAssembly.Module.customSections(module, name) -> Array<Section>
void WebAssemblyModuleCustomSections(
    const v8::FunctionCallbackInfo<v8::Value>& args) {
  HandleScope scope(args.GetIsolate());
  v8::Isolate* isolate = args.GetIsolate();
  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
  ScheduledErrorThrower thrower(i_isolate,
                                "WebAssembly.Module.customSections()");

  auto maybe_module = GetFirstArgumentAsModule(args, &thrower);
  if (thrower.error()) return;

  if (args[1]->IsUndefined()) {
    thrower.TypeError("Argument 1 is required");
    return;
  }

  i::MaybeHandle<i::Object> maybe_name =
      i::Object::ToString(i_isolate, Utils::OpenHandle(*args[1]));
  i::Handle<i::Object> name;
  if (!maybe_name.ToHandle(&name)) return;
  auto custom_sections =
      i::wasm::GetCustomSections(i_isolate, maybe_module.ToHandleChecked(),
                                 i::Handle<i::String>::cast(name), &thrower);
  if (thrower.error()) return;
  args.GetReturnValue().Set(Utils::ToLocal(custom_sections));
}

MaybeLocal<Value> WebAssemblyInstantiateImpl(Isolate* isolate,
                                             Local<Value> module,
                                             Local<Value> ffi) {
  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);

  i::MaybeHandle<i::Object> instance_object;
  {
    ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Instance()");

    // TODO(ahaas): These checks on the module should not be necessary here They
    // are just a workaround for https://crbug.com/837417.
    i::Handle<i::Object> module_obj = Utils::OpenHandle(*module);
    if (!module_obj->IsWasmModuleObject()) {
      thrower.TypeError("Argument 0 must be a WebAssembly.Module object");
      return {};
    }

    i::MaybeHandle<i::JSReceiver> maybe_imports =
        GetValueAsImports(ffi, &thrower);
    if (thrower.error()) return {};

    instance_object = i_isolate->wasm_engine()->SyncInstantiate(
        i_isolate, &thrower, i::Handle<i::WasmModuleObject>::cast(module_obj),
        maybe_imports, i::MaybeHandle<i::JSArrayBuffer>());
  }

  DCHECK_EQ(instance_object.is_null(), i_isolate->has_scheduled_exception());
  if (instance_object.is_null()) return {};
  return Utils::ToLocal(instance_object.ToHandleChecked());
}

// new WebAssembly.Instance(module, imports) -> WebAssembly.Instance
void WebAssemblyInstance(const v8::FunctionCallbackInfo<v8::Value>& args) {
  Isolate* isolate = args.GetIsolate();
  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
  i_isolate->CountUsage(
      v8::Isolate::UseCounterFeature::kWebAssemblyInstantiation);

  HandleScope scope(args.GetIsolate());
  if (i_isolate->wasm_instance_callback()(args)) return;

  ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Instance()");
  if (!args.IsConstructCall()) {
    thrower.TypeError("WebAssembly.Instance must be invoked with 'new'");
    return;
  }

  GetFirstArgumentAsModule(args, &thrower);
  if (thrower.error()) return;

  // If args.Length < 2, this will be undefined - see FunctionCallbackInfo.
  // We'll check for that in WebAssemblyInstantiateImpl.
  Local<Value> data = args[1];

  Local<Value> instance;
  if (WebAssemblyInstantiateImpl(isolate, args[0], data).ToLocal(&instance)) {
    args.GetReturnValue().Set(instance);
  }
}

// WebAssembly.instantiateStreaming(Response | Promise<Response> [, imports])
//   -> Promise<ResultObject>
// (where ResultObject has a "module" and an "instance" field)
void WebAssemblyInstantiateStreaming(
    const v8::FunctionCallbackInfo<v8::Value>& args) {
  v8::Isolate* isolate = args.GetIsolate();
  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
  i_isolate->CountUsage(
      v8::Isolate::UseCounterFeature::kWebAssemblyInstantiation);

  HandleScope scope(isolate);
  Local<Context> context = isolate->GetCurrentContext();
  const char* const kAPIMethodName = "WebAssembly.instantiateStreaming()";
  ScheduledErrorThrower thrower(i_isolate, kAPIMethodName);

  // Create and assign the return value of this function.
  ASSIGN(Promise::Resolver, result_resolver, Promise::Resolver::New(context));
  Local<Promise> promise = result_resolver->GetPromise();
  v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
  return_value.Set(promise);

  // Create an InstantiateResultResolver in case there is an issue with the
  // passed parameters.
  std::unique_ptr<i::wasm::InstantiationResultResolver> resolver(
      new InstantiateModuleResultResolver(i_isolate,
                                          Utils::OpenHandle(*promise)));

  if (!i::wasm::IsWasmCodegenAllowed(i_isolate, i_isolate->native_context())) {
    thrower.CompileError("Wasm code generation disallowed by embedder");
    resolver->OnInstantiationFailed(thrower.Reify());
    return;
  }

  // If args.Length < 2, this will be undefined - see FunctionCallbackInfo.
  Local<Value> ffi = args[1];
  i::MaybeHandle<i::JSReceiver> maybe_imports =
      GetValueAsImports(ffi, &thrower);

  if (thrower.error()) {
    resolver->OnInstantiationFailed(thrower.Reify());
    return;
  }

  // We start compilation now, we have no use for the
  // {InstantiationResultResolver}.
  resolver.reset();

  std::shared_ptr<i::wasm::CompilationResultResolver> compilation_resolver(
      new AsyncInstantiateCompileResultResolver(
          i_isolate, Utils::OpenHandle(*promise), maybe_imports));

  // Allocate the streaming decoder in a Managed so we can pass it to the
  // embedder.
  i::Handle<i::Managed<WasmStreaming>> data =
      i::Managed<WasmStreaming>::Allocate(
          i_isolate, 0,
          std::make_unique<WasmStreaming::WasmStreamingImpl>(
              isolate, kAPIMethodName, compilation_resolver));

  DCHECK_NOT_NULL(i_isolate->wasm_streaming_callback());
  ASSIGN(
      v8::Function, compile_callback,
      v8::Function::New(context, i_isolate->wasm_streaming_callback(),
                        Utils::ToLocal(i::Handle<i::Object>::cast(data)), 1));
  ASSIGN(
      v8::Function, reject_callback,
      v8::Function::New(context, WasmStreamingPromiseFailedCallback,
                        Utils::ToLocal(i::Handle<i::Object>::cast(data)), 1));

  // The parameter may be of type {Response} or of type {Promise<Response>}.
  // Treat either case of parameter as Promise.resolve(parameter)
  // as per https://www.w3.org/2001/tag/doc/promises-guide#resolve-arguments

  // Ending with:
  //    return Promise.resolve(parameter).then(compile_callback);
  ASSIGN(Promise::Resolver, input_resolver, Promise::Resolver::New(context));
  if (!input_resolver->Resolve(context, args[0]).IsJust()) return;

  // We do not have any use of the result here. The {compile_callback} will
  // start streaming compilation, which will eventually resolve the promise we
  // set as result value.
  USE(input_resolver->GetPromise()->Then(context, compile_callback,
                                         reject_callback));
}

// WebAssembly.instantiate(module, imports) -> WebAssembly.Instance
// WebAssembly.instantiate(bytes, imports) ->
//     {module: WebAssembly.Module, instance: WebAssembly.Instance}
void WebAssemblyInstantiate(const v8::FunctionCallbackInfo<v8::Value>& args) {
  constexpr const char* kAPIMethodName = "WebAssembly.instantiate()";
  v8::Isolate* isolate = args.GetIsolate();
  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
  i_isolate->CountUsage(
      v8::Isolate::UseCounterFeature::kWebAssemblyInstantiation);

  ScheduledErrorThrower thrower(i_isolate, kAPIMethodName);

  HandleScope scope(isolate);

  Local<Context> context = isolate->GetCurrentContext();

  ASSIGN(Promise::Resolver, promise_resolver, Promise::Resolver::New(context));
  Local<Promise> promise = promise_resolver->GetPromise();
  args.GetReturnValue().Set(promise);

  std::unique_ptr<i::wasm::InstantiationResultResolver> resolver(
      new InstantiateModuleResultResolver(i_isolate,
                                          Utils::OpenHandle(*promise)));

  Local<Value> first_arg_value = args[0];
  i::Handle<i::Object> first_arg = Utils::OpenHandle(*first_arg_value);
  if (!first_arg->IsJSObject()) {
    thrower.TypeError(
        "Argument 0 must be a buffer source or a WebAssembly.Module object");
    resolver->OnInstantiationFailed(thrower.Reify());
    return;
  }

  // If args.Length < 2, this will be undefined - see FunctionCallbackInfo.
  Local<Value> ffi = args[1];
  i::MaybeHandle<i::JSReceiver> maybe_imports =
      GetValueAsImports(ffi, &thrower);

  if (thrower.error()) {
    resolver->OnInstantiationFailed(thrower.Reify());
    return;
  }

  if (first_arg->IsWasmModuleObject()) {
    i::Handle<i::WasmModuleObject> module_obj =
        i::Handle<i::WasmModuleObject>::cast(first_arg);

    i_isolate->wasm_engine()->AsyncInstantiate(i_isolate, std::move(resolver),
                                               module_obj, maybe_imports);
    return;
  }

  bool is_shared = false;
  auto bytes = GetFirstArgumentAsBytes(args, &thrower, &is_shared);
  if (thrower.error()) {
    resolver->OnInstantiationFailed(thrower.Reify());
    return;
  }

  // We start compilation now, we have no use for the
  // {InstantiationResultResolver}.
  resolver.reset();

  std::shared_ptr<i::wasm::CompilationResultResolver> compilation_resolver(
      new AsyncInstantiateCompileResultResolver(
          i_isolate, Utils::OpenHandle(*promise), maybe_imports));

  // The first parameter is a buffer source, we have to check if we are allowed
  // to compile it.
  if (!i::wasm::IsWasmCodegenAllowed(i_isolate, i_isolate->native_context())) {
    thrower.CompileError("Wasm code generation disallowed by embedder");
    compilation_resolver->OnCompilationFailed(thrower.Reify());
    return;
  }

  // Asynchronous compilation handles copying wire bytes if necessary.
  auto enabled_features = i::wasm::WasmFeatures::FromIsolate(i_isolate);
  i_isolate->wasm_engine()->AsyncCompile(i_isolate, enabled_features,
                                         std::move(compilation_resolver), bytes,
                                         is_shared, kAPIMethodName);
}

bool GetIntegerProperty(v8::Isolate* isolate, ErrorThrower* thrower,
                        Local<Context> context, v8::Local<v8::Value> value,
                        i::Handle<i::String> property_name, int64_t* result,
                        int64_t lower_bound, uint64_t upper_bound) {
  uint32_t number;
  if (!EnforceUint32(property_name, value, context, thrower, &number)) {
    return false;
  }
  if (number < lower_bound) {
    thrower->RangeError("Property '%s': value %" PRIu32
                        " is below the lower bound %" PRIx64,
                        property_name->ToCString().get(), number, lower_bound);
    return false;
  }
  if (number > upper_bound) {
    thrower->RangeError("Property '%s': value %" PRIu32
                        " is above the upper bound %" PRIu64,
                        property_name->ToCString().get(), number, upper_bound);
    return false;
  }

  *result = static_cast<int64_t>(number);
  return true;
}

bool GetOptionalIntegerProperty(v8::Isolate* isolate, ErrorThrower* thrower,
                                Local<Context> context,
                                Local<v8::Object> object,
                                Local<String> property, bool* has_property,
                                int64_t* result, int64_t lower_bound,
                                uint64_t upper_bound) {
  v8::Local<v8::Value> value;
  if (!object->Get(context, property).ToLocal(&value)) {
    return false;
  }

  // Web IDL: dictionary presence
  // https://heycam.github.io/webidl/#dfn-present
  if (value->IsUndefined()) {
    if (has_property != nullptr) *has_property = false;
    return true;
  }

  if (has_property != nullptr) *has_property = true;
  i::Handle<i::String> property_name = v8::Utils::OpenHandle(*property);

  return GetIntegerProperty(isolate, thrower, context, value, property_name,
                            result, lower_bound, upper_bound);
}

// Fetch 'initial' or 'minimum' property from object. If both are provided,
// 'initial' is used.
// TODO(aseemgarg): change behavior when the following bug is resolved:
// https://github.com/WebAssembly/js-types/issues/6
bool GetInitialOrMinimumProperty(v8::Isolate* isolate, ErrorThrower* thrower,
                                 Local<Context> context,
                                 Local<v8::Object> object, int64_t* result,
                                 int64_t lower_bound, uint64_t upper_bound) {
  bool has_initial = false;
  if (!GetOptionalIntegerProperty(isolate, thrower, context, object,
                                  v8_str(isolate, "initial"), &has_initial,
                                  result, lower_bound, upper_bound)) {
    return false;
  }
  auto enabled_features = i::wasm::WasmFeatures::FromFlags();
  if (!has_initial && enabled_features.has_type_reflection()) {
    if (!GetOptionalIntegerProperty(isolate, thrower, context, object,
                                    v8_str(isolate, "minimum"), &has_initial,
                                    result, lower_bound, upper_bound)) {
      return false;
    }
  }
  if (!has_initial) {
    // TODO(aseemgarg): update error message when the spec issue is resolved.
    thrower->TypeError("Property 'initial' is required");
    return false;
  }
  return true;
}

// new WebAssembly.Table(args) -> WebAssembly.Table
void WebAssemblyTable(const v8::FunctionCallbackInfo<v8::Value>& args) {
  v8::Isolate* isolate = args.GetIsolate();
  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
  HandleScope scope(isolate);
  ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Module()");
  if (!args.IsConstructCall()) {
    thrower.TypeError("WebAssembly.Table must be invoked with 'new'");
    return;
  }
  if (!args[0]->IsObject()) {
    thrower.TypeError("Argument 0 must be a table descriptor");
    return;
  }
  Local<Context> context = isolate->GetCurrentContext();
  Local<v8::Object> descriptor = Local<Object>::Cast(args[0]);
  i::wasm::ValueType type;
  // The descriptor's 'element'.
  {
    v8::MaybeLocal<v8::Value> maybe =
        descriptor->Get(context, v8_str(isolate, "element"));
    v8::Local<v8::Value> value;
    if (!maybe.ToLocal(&value)) return;
    v8::Local<v8::String> string;
    if (!value->ToString(context).ToLocal(&string)) return;
    auto enabled_features = i::wasm::WasmFeatures::FromFlags();
    // The JS api uses 'anyfunc' instead of 'funcref'.
    if (string->StringEquals(v8_str(isolate, "anyfunc"))) {
      type = i::wasm::kWasmFuncRef;
    } else if (enabled_features.has_reftypes() &&
               string->StringEquals(v8_str(isolate, "externref"))) {
      type = i::wasm::kWasmExternRef;
    } else {
      thrower.TypeError(
          "Descriptor property 'element' must be a WebAssembly reference type");
      return;
    }
  }

  int64_t initial = 0;
  if (!GetInitialOrMinimumProperty(isolate, &thrower, context, descriptor,
                                   &initial, 0,
                                   i::wasm::max_table_init_entries())) {
    return;
  }
  // The descriptor's 'maximum'.
  int64_t maximum = -1;
  bool has_maximum = true;
  if (!GetOptionalIntegerProperty(isolate, &thrower, context, descriptor,
                                  v8_str(isolate, "maximum"), &has_maximum,
                                  &maximum, initial,
                                  std::numeric_limits<uint32_t>::max())) {
    return;
  }

  i::Handle<i::FixedArray> fixed_array;
  i::Handle<i::JSObject> table_obj =
      i::WasmTableObject::New(i_isolate, i::Handle<i::WasmInstanceObject>(),
                              type, static_cast<uint32_t>(initial), has_maximum,
                              static_cast<uint32_t>(maximum), &fixed_array);
  v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
  return_value.Set(Utils::ToLocal(table_obj));
}

void WebAssemblyMemory(const v8::FunctionCallbackInfo<v8::Value>& args) {
  v8::Isolate* isolate = args.GetIsolate();
  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
  HandleScope scope(isolate);
  ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Memory()");
  if (!args.IsConstructCall()) {
    thrower.TypeError("WebAssembly.Memory must be invoked with 'new'");
    return;
  }
  if (!args[0]->IsObject()) {
    thrower.TypeError("Argument 0 must be a memory descriptor");
    return;
  }
  Local<Context> context = isolate->GetCurrentContext();
  Local<v8::Object> descriptor = Local<Object>::Cast(args[0]);

  int64_t initial = 0;
  if (!GetInitialOrMinimumProperty(isolate, &thrower, context, descriptor,
                                   &initial, 0, i::wasm::max_mem_pages())) {
    return;
  }
  // The descriptor's 'maximum'.
  int64_t maximum = -1;
  if (!GetOptionalIntegerProperty(isolate, &thrower, context, descriptor,
                                  v8_str(isolate, "maximum"), nullptr, &maximum,
                                  initial, i::wasm::max_mem_pages())) {
    return;
  }

  auto shared = i::SharedFlag::kNotShared;
  auto enabled_features = i::wasm::WasmFeatures::FromIsolate(i_isolate);
  if (enabled_features.has_threads()) {
    // Shared property of descriptor
    Local<String> shared_key = v8_str(isolate, "shared");
    v8::MaybeLocal<v8::Value> maybe_value =
        descriptor->Get(context, shared_key);
    v8::Local<v8::Value> value;
    if (maybe_value.ToLocal(&value)) {
      shared = value->BooleanValue(isolate) ? i::SharedFlag::kShared
                                            : i::SharedFlag::kNotShared;
    } else {
      DCHECK(i_isolate->has_scheduled_exception());
      return;
    }

    // Throw TypeError if shared is true, and the descriptor has no "maximum"
    if (shared == i::SharedFlag::kShared && maximum == -1) {
      thrower.TypeError(
          "If shared is true, maximum property should be defined.");
      return;
    }
  }

  i::Handle<i::JSObject> memory_obj;
  if (!i::WasmMemoryObject::New(i_isolate, static_cast<uint32_t>(initial),
                                static_cast<uint32_t>(maximum), shared)
           .ToHandle(&memory_obj)) {
    thrower.RangeError("could not allocate memory");
    return;
  }
  if (shared == i::SharedFlag::kShared) {
    i::Handle<i::JSArrayBuffer> buffer(
        i::Handle<i::WasmMemoryObject>::cast(memory_obj)->array_buffer(),
        i_isolate);
    Maybe<bool> result =
        buffer->SetIntegrityLevel(buffer, i::FROZEN, i::kDontThrow);
    if (!result.FromJust()) {
      thrower.TypeError(
          "Status of setting SetIntegrityLevel of buffer is false.");
      return;
    }
  }
  args.GetReturnValue().Set(Utils::ToLocal(memory_obj));
}

// Determines the type encoded in a value type property (e.g. type reflection).
// Returns false if there was an exception, true upon success. On success the
// outgoing {type} is set accordingly, or set to {wasm::kWasmStmt} in case the
// type could not be properly recognized.
bool GetValueType(Isolate* isolate, MaybeLocal<Value> maybe,
                  Local<Context> context, i::wasm::ValueType* type,
                  i::wasm::WasmFeatures enabled_features) {
  v8::Local<v8::Value> value;
  if (!maybe.ToLocal(&value)) return false;
  v8::Local<v8::String> string;
  if (!value->ToString(context).ToLocal(&string)) return false;
  if (string->StringEquals(v8_str(isolate, "i32"))) {
    *type = i::wasm::kWasmI32;
  } else if (string->StringEquals(v8_str(isolate, "f32"))) {
    *type = i::wasm::kWasmF32;
  } else if (string->StringEquals(v8_str(isolate, "i64"))) {
    *type = i::wasm::kWasmI64;
  } else if (string->StringEquals(v8_str(isolate, "f64"))) {
    *type = i::wasm::kWasmF64;
  } else if (enabled_features.has_reftypes() &&
             string->StringEquals(v8_str(isolate, "externref"))) {
    *type = i::wasm::kWasmExternRef;
  } else if (enabled_features.has_reftypes() &&
             string->StringEquals(v8_str(isolate, "anyfunc"))) {
    // The JS api spec uses 'anyfunc' instead of 'funcref'.
    *type = i::wasm::kWasmFuncRef;
  } else if (enabled_features.has_eh() &&
             string->StringEquals(v8_str(isolate, "exnref"))) {
    *type = i::wasm::kWasmExnRef;
  } else if (enabled_features.has_gc() &&
             string->StringEquals(v8_str(isolate, "eqref"))) {
    *type = i::wasm::kWasmEqRef;
  } else {
    // Unrecognized type.
    *type = i::wasm::kWasmStmt;
  }
  return true;
}

// WebAssembly.Global
void WebAssemblyGlobal(const v8::FunctionCallbackInfo<v8::Value>& args) {
  v8::Isolate* isolate = args.GetIsolate();
  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
  HandleScope scope(isolate);
  ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Global()");
  if (!args.IsConstructCall()) {
    thrower.TypeError("WebAssembly.Global must be invoked with 'new'");
    return;
  }
  if (!args[0]->IsObject()) {
    thrower.TypeError("Argument 0 must be a global descriptor");
    return;
  }
  Local<Context> context = isolate->GetCurrentContext();
  Local<v8::Object> descriptor = Local<Object>::Cast(args[0]);
  auto enabled_features = i::wasm::WasmFeatures::FromIsolate(i_isolate);

  // The descriptor's 'mutable'.
  bool is_mutable = false;
  {
    Local<String> mutable_key = v8_str(isolate, "mutable");
    v8::MaybeLocal<v8::Value> maybe = descriptor->Get(context, mutable_key);
    v8::Local<v8::Value> value;
    if (maybe.ToLocal(&value)) {
      is_mutable = value->BooleanValue(isolate);
    } else {
      DCHECK(i_isolate->has_scheduled_exception());
      return;
    }
  }

  // The descriptor's type, called 'value'. It is called 'value' because this
  // descriptor is planned to be re-used as the global's type for reflection,
  // so calling it 'type' is redundant.
  i::wasm::ValueType type;
  {
    v8::MaybeLocal<v8::Value> maybe =
        descriptor->Get(context, v8_str(isolate, "value"));
    if (!GetValueType(isolate, maybe, context, &type, enabled_features)) return;
    if (type == i::wasm::kWasmStmt) {
      thrower.TypeError(
          "Descriptor property 'value' must be a WebAssembly type");
      return;
    }
  }

  const uint32_t offset = 0;
  i::MaybeHandle<i::WasmGlobalObject> maybe_global_obj =
      i::WasmGlobalObject::New(i_isolate, i::Handle<i::WasmInstanceObject>(),
                               i::MaybeHandle<i::JSArrayBuffer>(),
                               i::MaybeHandle<i::FixedArray>(), type, offset,
                               is_mutable);

  i::Handle<i::WasmGlobalObject> global_obj;
  if (!maybe_global_obj.ToHandle(&global_obj)) {
    thrower.RangeError("could not allocate memory");
    return;
  }

  // Convert value to a WebAssembly value, the default value is 0.
  Local<v8::Value> value = Local<Value>::Cast(args[1]);
  switch (type.kind()) {
    case i::wasm::ValueType::kI32: {
      int32_t i32_value = 0;
      if (!value->IsUndefined()) {
        v8::Local<v8::Int32> int32_value;
        if (!value->ToInt32(context).ToLocal(&int32_value)) return;
        if (!int32_value->Int32Value(context).To(&i32_value)) return;
      }
      global_obj->SetI32(i32_value);
      break;
    }
    case i::wasm::ValueType::kI64: {
      int64_t i64_value = 0;
      if (!value->IsUndefined()) {
        if (!enabled_features.has_bigint()) {
          thrower.TypeError("Can't set the value of i64 WebAssembly.Global");
          return;
        }

        v8::Local<v8::BigInt> bigint_value;
        if (!value->ToBigInt(context).ToLocal(&bigint_value)) return;
        i64_value = bigint_value->Int64Value();
      }
      global_obj->SetI64(i64_value);
      break;
    }
    case i::wasm::ValueType::kF32: {
      float f32_value = 0;
      if (!value->IsUndefined()) {
        double f64_value = 0;
        v8::Local<v8::Number> number_value;
        if (!value->ToNumber(context).ToLocal(&number_value)) return;
        if (!number_value->NumberValue(context).To(&f64_value)) return;
        f32_value = i::DoubleToFloat32(f64_value);
      }
      global_obj->SetF32(f32_value);
      break;
    }
    case i::wasm::ValueType::kF64: {
      double f64_value = 0;
      if (!value->IsUndefined()) {
        v8::Local<v8::Number> number_value;
        if (!value->ToNumber(context).ToLocal(&number_value)) return;
        if (!number_value->NumberValue(context).To(&f64_value)) return;
      }
      global_obj->SetF64(f64_value);
      break;
    }
    case i::wasm::ValueType::kRef:
    case i::wasm::ValueType::kOptRef: {
      switch (type.heap_representation()) {
        case i::wasm::HeapType::kExtern:
        case i::wasm::HeapType::kExn: {
          if (args.Length() < 2) {
            // When no initial value is provided, we have to use the WebAssembly
            // default value 'null', and not the JS default value 'undefined'.
            global_obj->SetExternRef(i_isolate->factory()->null_value());
            break;
          }
          global_obj->SetExternRef(Utils::OpenHandle(*value));
          break;
        }
        case i::wasm::HeapType::kFunc: {
          if (args.Length() < 2) {
            // When no initial value is provided, we have to use the WebAssembly
            // default value 'null', and not the JS default value 'undefined'.
            global_obj->SetFuncRef(i_isolate,
                                   i_isolate->factory()->null_value());
            break;
          }

          if (!global_obj->SetFuncRef(i_isolate, Utils::OpenHandle(*value))) {
            thrower.TypeError(
                "The value of funcref globals must be null or an "
                "exported function");
          }
          break;
        }
        case i::wasm::HeapType::kEq:
        default:
          // TODO(7748): Implement these.
          UNIMPLEMENTED();
      }
      break;
    }
    case i::wasm::ValueType::kRtt:
      // TODO(7748): Implement.
      UNIMPLEMENTED();
    case i::wasm::ValueType::kI8:
    case i::wasm::ValueType::kI16:
    case i::wasm::ValueType::kStmt:
    case i::wasm::ValueType::kS128:
    case i::wasm::ValueType::kBottom:
      UNREACHABLE();
  }

  i::Handle<i::JSObject> global_js_object(global_obj);
  args.GetReturnValue().Set(Utils::ToLocal(global_js_object));
}

// WebAssembly.Exception
void WebAssemblyException(const v8::FunctionCallbackInfo<v8::Value>& args) {
  v8::Isolate* isolate = args.GetIsolate();
  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
  HandleScope scope(isolate);
  ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Exception()");
  thrower.TypeError("WebAssembly.Exception cannot be called");
}

namespace {

uint32_t GetIterableLength(i::Isolate* isolate, Local<Context> context,
                           Local<Object> iterable) {
  Local<String> length = Utils::ToLocal(isolate->factory()->length_string());
  MaybeLocal<Value> property = iterable->Get(context, length);
  if (property.IsEmpty()) return i::kMaxUInt32;
  MaybeLocal<Uint32> number = property.ToLocalChecked()->ToArrayIndex(context);
  if (number.IsEmpty()) return i::kMaxUInt32;
  DCHECK_NE(i::kMaxUInt32, number.ToLocalChecked()->Value());
  return number.ToLocalChecked()->Value();
}

}  // namespace

// WebAssembly.Function
void WebAssemblyFunction(const v8::FunctionCallbackInfo<v8::Value>& args) {
  v8::Isolate* isolate = args.GetIsolate();
  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
  HandleScope scope(isolate);
  ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Function()");
  if (!args.IsConstructCall()) {
    thrower.TypeError("WebAssembly.Function must be invoked with 'new'");
    return;
  }
  if (!args[0]->IsObject()) {
    thrower.TypeError("Argument 0 must be a function type");
    return;
  }
  Local<Object> function_type = Local<Object>::Cast(args[0]);
  Local<Context> context = isolate->GetCurrentContext();
  auto enabled_features = i::wasm::WasmFeatures::FromIsolate(i_isolate);

  // Load the 'parameters' property of the function type.
  Local<String> parameters_key = v8_str(isolate, "parameters");
  v8::MaybeLocal<v8::Value> parameters_maybe =
      function_type->Get(context, parameters_key);
  v8::Local<v8::Value> parameters_value;
  if (!parameters_maybe.ToLocal(&parameters_value)) return;
  if (!parameters_value->IsObject()) {
    thrower.TypeError("Argument 0 must be a function type with 'parameters'");
    return;
  }
  Local<Object> parameters = parameters_value.As<Object>();
  uint32_t parameters_len = GetIterableLength(i_isolate, context, parameters);
  if (parameters_len == i::kMaxUInt32) {
    thrower.TypeError("Argument 0 contains parameters without 'length'");
    return;
  }
  if (parameters_len > i::wasm::kV8MaxWasmFunctionParams) {
    thrower.TypeError("Argument 0 contains too many parameters");
    return;
  }

  // Load the 'results' property of the function type.
  Local<String> results_key = v8_str(isolate, "results");
  v8::MaybeLocal<v8::Value> results_maybe =
      function_type->Get(context, results_key);
  v8::Local<v8::Value> results_value;
  if (!results_maybe.ToLocal(&results_value)) return;
  if (!results_value->IsObject()) {
    thrower.TypeError("Argument 0 must be a function type with 'results'");
    return;
  }
  Local<Object> results = results_value.As<Object>();
  uint32_t results_len = GetIterableLength(i_isolate, context, results);
  if (results_len == i::kMaxUInt32) {
    thrower.TypeError("Argument 0 contains results without 'length'");
    return;
  }
  if (results_len > (enabled_features.has_mv()
                         ? i::wasm::kV8MaxWasmFunctionMultiReturns
                         : i::wasm::kV8MaxWasmFunctionReturns)) {
    thrower.TypeError("Argument 0 contains too many results");
    return;
  }

  // Decode the function type and construct a signature.
  i::Zone zone(i_isolate->allocator(), ZONE_NAME);
  i::wasm::FunctionSig::Builder builder(&zone, results_len, parameters_len);
  for (uint32_t i = 0; i < parameters_len; ++i) {
    i::wasm::ValueType type;
    MaybeLocal<Value> maybe = parameters->Get(context, i);
    if (!GetValueType(isolate, maybe, context, &type, enabled_features)) return;
    if (type == i::wasm::kWasmStmt) {
      thrower.TypeError(
          "Argument 0 parameter type at index #%u must be a value type", i);
      return;
    }
    builder.AddParam(type);
  }
  for (uint32_t i = 0; i < results_len; ++i) {
    i::wasm::ValueType type;
    MaybeLocal<Value> maybe = results->Get(context, i);
    if (!GetValueType(isolate, maybe, context, &type, enabled_features)) return;
    if (type == i::wasm::kWasmStmt) {
      thrower.TypeError(
          "Argument 0 result type at index #%u must be a value type", i);
      return;
    }
    builder.AddReturn(type);
  }

  if (!args[1]->IsFunction()) {
    thrower.TypeError("Argument 1 must be a function");
    return;
  }
  const i::wasm::FunctionSig* sig = builder.Build();

  i::Handle<i::JSReceiver> callable =
      Utils::OpenHandle(*args[1].As<Function>());
  if (i::WasmExportedFunction::IsWasmExportedFunction(*callable)) {
    if (*i::Handle<i::WasmExportedFunction>::cast(callable)->sig() == *sig) {
      args.GetReturnValue().Set(Utils::ToLocal(callable));
      return;
    }

    thrower.TypeError(
        "The signature of Argument 1 (a WebAssembly function) does "
        "not match the signature specified in Argument 0");
    return;
  }

  if (i::WasmJSFunction::IsWasmJSFunction(*callable)) {
    if (i::Handle<i::WasmJSFunction>::cast(callable)->MatchesSignature(sig)) {
      args.GetReturnValue().Set(Utils::ToLocal(callable));
      return;
    }

    thrower.TypeError(
        "The signature of Argument 1 (a WebAssembly function) does "
        "not match the signature specified in Argument 0");
    return;
  }

  i::Handle<i::JSFunction> result =
      i::WasmJSFunction::New(i_isolate, sig, callable);
  args.GetReturnValue().Set(Utils::ToLocal(result));
}

// WebAssembly.Function.type(WebAssembly.Function) -> FunctionType
void WebAssemblyFunctionType(const v8::FunctionCallbackInfo<v8::Value>& args) {
  v8::Isolate* isolate = args.GetIsolate();
  HandleScope scope(isolate);
  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
  ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Function.type()");

  const i::wasm::FunctionSig* sig;
  i::Zone zone(i_isolate->allocator(), ZONE_NAME);
  i::Handle<i::Object> arg0 = Utils::OpenHandle(*args[0]);
  if (i::WasmExportedFunction::IsWasmExportedFunction(*arg0)) {
    sig = i::Handle<i::WasmExportedFunction>::cast(arg0)->sig();
  } else if (i::WasmJSFunction::IsWasmJSFunction(*arg0)) {
    sig = i::Handle<i::WasmJSFunction>::cast(arg0)->GetSignature(&zone);
  } else {
    thrower.TypeError("Argument 0 must be a WebAssembly.Function");
    return;
  }

  auto type = i::wasm::GetTypeForFunction(i_isolate, sig);
  args.GetReturnValue().Set(Utils::ToLocal(type));
}

constexpr const char* kName_WasmGlobalObject = "WebAssembly.Global";
constexpr const char* kName_WasmMemoryObject = "WebAssembly.Memory";
constexpr const char* kName_WasmInstanceObject = "WebAssembly.Instance";
constexpr const char* kName_WasmTableObject = "WebAssembly.Table";

#define EXTRACT_THIS(var, WasmType)                                  \
  i::Handle<i::WasmType> var;                                        \
  {                                                                  \
    i::Handle<i::Object> this_arg = Utils::OpenHandle(*args.This()); \
    if (!this_arg->Is##WasmType()) {                                 \
      thrower.TypeError("Receiver is not a %s", kName_##WasmType);   \
      return;                                                        \
    }                                                                \
    var = i::Handle<i::WasmType>::cast(this_arg);                    \
  }

void WebAssemblyInstanceGetExports(
    const v8::FunctionCallbackInfo<v8::Value>& args) {
  v8::Isolate* isolate = args.GetIsolate();
  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
  HandleScope scope(isolate);
  ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Instance.exports()");
  EXTRACT_THIS(receiver, WasmInstanceObject);
  i::Handle<i::JSObject> exports_object(receiver->exports_object(), i_isolate);
  args.GetReturnValue().Set(Utils::ToLocal(exports_object));
}

void WebAssemblyTableGetLength(
    const v8::FunctionCallbackInfo<v8::Value>& args) {
  v8::Isolate* isolate = args.GetIsolate();
  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
  HandleScope scope(isolate);
  ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Table.length()");
  EXTRACT_THIS(receiver, WasmTableObject);
  args.GetReturnValue().Set(
      v8::Number::New(isolate, receiver->current_length()));
}

// WebAssembly.Table.grow(num, init_value = null) -> num
void WebAssemblyTableGrow(const v8::FunctionCallbackInfo<v8::Value>& args) {
  v8::Isolate* isolate = args.GetIsolate();
  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
  HandleScope scope(isolate);
  ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Table.grow()");
  Local<Context> context = isolate->GetCurrentContext();
  EXTRACT_THIS(receiver, WasmTableObject);

  uint32_t grow_by;
  if (!EnforceUint32("Argument 0", args[0], context, &thrower, &grow_by)) {
    return;
  }

  i::Handle<i::Object> init_value = i_isolate->factory()->null_value();
  auto enabled_features = i::wasm::WasmFeatures::FromIsolate(i_isolate);
  if (enabled_features.has_typed_funcref()) {
    if (args.Length() >= 2 && !args[1]->IsUndefined()) {
      init_value = Utils::OpenHandle(*args[1]);
    }
    if (!i::WasmTableObject::IsValidElement(i_isolate, receiver, init_value)) {
      thrower.TypeError("Argument 1 must be a valid type for the table");
      return;
    }
  }

  int old_size =
      i::WasmTableObject::Grow(i_isolate, receiver, grow_by, init_value);

  if (old_size < 0) {
    thrower.RangeError("failed to grow table by %u", grow_by);
    return;
  }
  v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
  return_value.Set(old_size);
}

// WebAssembly.Table.get(num) -> JSFunction
void WebAssemblyTableGet(const v8::FunctionCallbackInfo<v8::Value>& args) {
  v8::Isolate* isolate = args.GetIsolate();
  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
  HandleScope scope(isolate);
  ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Table.get()");
  Local<Context> context = isolate->GetCurrentContext();
  EXTRACT_THIS(receiver, WasmTableObject);

  uint32_t index;
  if (!EnforceUint32("Argument 0", args[0], context, &thrower, &index)) {
    return;
  }
  if (!i::WasmTableObject::IsInBounds(i_isolate, receiver, index)) {
    thrower.RangeError("invalid index %u into function table", index);
    return;
  }

  i::Handle<i::Object> result =
      i::WasmTableObject::Get(i_isolate, receiver, index);

  v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
  return_value.Set(Utils::ToLocal(result));
}

// WebAssembly.Table.set(num, JSFunction)
void WebAssemblyTableSet(const v8::FunctionCallbackInfo<v8::Value>& args) {
  v8::Isolate* isolate = args.GetIsolate();
  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
  HandleScope scope(isolate);
  ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Table.set()");
  Local<Context> context = isolate->GetCurrentContext();
  EXTRACT_THIS(table_object, WasmTableObject);

  // Parameter 0.
  uint32_t index;
  if (!EnforceUint32("Argument 0", args[0], context, &thrower, &index)) {
    return;
  }
  if (!i::WasmTableObject::IsInBounds(i_isolate, table_object, index)) {
    thrower.RangeError("invalid index %u into function table", index);
    return;
  }

  i::Handle<i::Object> element = Utils::OpenHandle(*args[1]);
  if (!i::WasmTableObject::IsValidElement(i_isolate, table_object, element)) {
    thrower.TypeError(
        "Argument 1 must be null or a WebAssembly function of type compatible "
        "to 'this'");
    return;
  }
  i::WasmTableObject::Set(i_isolate, table_object, index, element);
}

// WebAssembly.Table.type(WebAssembly.Table) -> TableType
void WebAssemblyTableType(const v8::FunctionCallbackInfo<v8::Value>& args) {
  v8::Isolate* isolate = args.GetIsolate();
  HandleScope scope(isolate);
  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
  ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Table.type()");

  auto maybe_table = GetFirstArgumentAsTable(args, &thrower);
  if (thrower.error()) return;
  i::Handle<i::WasmTableObject> table = maybe_table.ToHandleChecked();
  base::Optional<uint32_t> max_size;
  if (!table->maximum_length().IsUndefined()) {
    uint64_t max_size64 = table->maximum_length().Number();
    DCHECK_LE(max_size64, std::numeric_limits<uint32_t>::max());
    max_size.emplace(static_cast<uint32_t>(max_size64));
  }
  auto type = i::wasm::GetTypeForTable(i_isolate, table->type(),
                                       table->current_length(), max_size);
  args.GetReturnValue().Set(Utils::ToLocal(type));
}

// WebAssembly.Memory.grow(num) -> num
void WebAssemblyMemoryGrow(const v8::FunctionCallbackInfo<v8::Value>& args) {
  v8::Isolate* isolate = args.GetIsolate();
  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
  HandleScope scope(isolate);
  ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Memory.grow()");
  Local<Context> context = isolate->GetCurrentContext();
  EXTRACT_THIS(receiver, WasmMemoryObject);

  uint32_t delta_size;
  if (!EnforceUint32("Argument 0", args[0], context, &thrower, &delta_size)) {
    return;
  }

  uint64_t max_size64 = receiver->maximum_pages();
  if (max_size64 > uint64_t{i::wasm::max_mem_pages()}) {
    max_size64 = i::wasm::max_mem_pages();
  }
  i::Handle<i::JSArrayBuffer> old_buffer(receiver->array_buffer(), i_isolate);

  DCHECK_LE(max_size64, std::numeric_limits<uint32_t>::max());

  uint64_t old_size64 = old_buffer->byte_length() / i::wasm::kWasmPageSize;
  uint64_t new_size64 = old_size64 + static_cast<uint64_t>(delta_size);

  if (new_size64 > max_size64) {
    thrower.RangeError("Maximum memory size exceeded");
    return;
  }

  int32_t ret = i::WasmMemoryObject::Grow(i_isolate, receiver, delta_size);
  if (ret == -1) {
    thrower.RangeError("Unable to grow instance memory.");
    return;
  }
  v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
  return_value.Set(ret);
}

// WebAssembly.Memory.buffer -> ArrayBuffer
void WebAssemblyMemoryGetBuffer(
    const v8::FunctionCallbackInfo<v8::Value>& args) {
  v8::Isolate* isolate = args.GetIsolate();
  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
  HandleScope scope(isolate);
  ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Memory.buffer");
  EXTRACT_THIS(receiver, WasmMemoryObject);

  i::Handle<i::Object> buffer_obj(receiver->array_buffer(), i_isolate);
  DCHECK(buffer_obj->IsJSArrayBuffer());
  i::Handle<i::JSArrayBuffer> buffer(i::JSArrayBuffer::cast(*buffer_obj),
                                     i_isolate);
  if (buffer->is_shared()) {
    // TODO(gdeepti): More needed here for when cached buffer, and current
    // buffer are out of sync, handle that here when bounds checks, and Grow
    // are handled correctly.
    Maybe<bool> result =
        buffer->SetIntegrityLevel(buffer, i::FROZEN, i::kDontThrow);
    if (!result.FromJust()) {
      thrower.TypeError(
          "Status of setting SetIntegrityLevel of buffer is false.");
    }
  }
  v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
  return_value.Set(Utils::ToLocal(buffer));
}

// WebAssembly.Memory.type(WebAssembly.Memory) -> MemoryType
void WebAssemblyMemoryType(const v8::FunctionCallbackInfo<v8::Value>& args) {
  v8::Isolate* isolate = args.GetIsolate();
  HandleScope scope(isolate);
  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
  ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Memory.type()");

  auto maybe_memory = GetFirstArgumentAsMemory(args, &thrower);
  if (thrower.error()) return;
  i::Handle<i::WasmMemoryObject> memory = maybe_memory.ToHandleChecked();
  i::Handle<i::JSArrayBuffer> buffer(memory->array_buffer(), i_isolate);
  size_t curr_size = buffer->byte_length() / i::wasm::kWasmPageSize;
  DCHECK_LE(curr_size, std::numeric_limits<uint32_t>::max());
  uint32_t min_size = static_cast<uint32_t>(curr_size);
  base::Optional<uint32_t> max_size;
  if (memory->has_maximum_pages()) {
    uint64_t max_size64 = memory->maximum_pages();
    DCHECK_LE(max_size64, std::numeric_limits<uint32_t>::max());
    max_size.emplace(static_cast<uint32_t>(max_size64));
  }
  auto type = i::wasm::GetTypeForMemory(i_isolate, min_size, max_size);
  args.GetReturnValue().Set(Utils::ToLocal(type));
}

void WebAssemblyGlobalGetValueCommon(
    const v8::FunctionCallbackInfo<v8::Value>& args, const char* name) {
  v8::Isolate* isolate = args.GetIsolate();
  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
  HandleScope scope(isolate);
  ScheduledErrorThrower thrower(i_isolate, name);
  EXTRACT_THIS(receiver, WasmGlobalObject);

  v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();

  switch (receiver->type().kind()) {
    case i::wasm::ValueType::kI32:
      return_value.Set(receiver->GetI32());
      break;
    case i::wasm::ValueType::kI64: {
      auto enabled_features = i::wasm::WasmFeatures::FromIsolate(i_isolate);
      if (enabled_features.has_bigint()) {
        Local<BigInt> value = BigInt::New(isolate, receiver->GetI64());
        return_value.Set(value);
      } else {
        thrower.TypeError("Can't get the value of i64 WebAssembly.Global");
      }
      break;
    }
    case i::wasm::ValueType::kF32:
      return_value.Set(receiver->GetF32());
      break;
    case i::wasm::ValueType::kF64:
      return_value.Set(receiver->GetF64());
      break;
    case i::wasm::ValueType::kS128:
      thrower.TypeError("Can't get the value of s128 WebAssembly.Global");
      break;
    case i::wasm::ValueType::kRef:
    case i::wasm::ValueType::kOptRef:
      switch (receiver->type().heap_representation()) {
        case i::wasm::HeapType::kExtern:
        case i::wasm::HeapType::kFunc:
        case i::wasm::HeapType::kExn:
          return_value.Set(Utils::ToLocal(receiver->GetRef()));
          break;
        case i::wasm::HeapType::kEq:
        default:
          // TODO(7748): Implement these.
          UNIMPLEMENTED();
          break;
      }
      break;
    case i::wasm::ValueType::kRtt:
      UNIMPLEMENTED();  // TODO(7748): Implement.
      break;
    case i::wasm::ValueType::kI8:
    case i::wasm::ValueType::kI16:
    case i::wasm::ValueType::kBottom:
    case i::wasm::ValueType::kStmt:
      UNREACHABLE();
  }
}

// WebAssembly.Global.valueOf() -> num
void WebAssemblyGlobalValueOf(const v8::FunctionCallbackInfo<v8::Value>& args) {
  return WebAssemblyGlobalGetValueCommon(args, "WebAssembly.Global.valueOf()");
}

// get WebAssembly.Global.value -> num
void WebAssemblyGlobalGetValue(
    const v8::FunctionCallbackInfo<v8::Value>& args) {
  return WebAssemblyGlobalGetValueCommon(args, "get WebAssembly.Global.value");
}

// set WebAssembly.Global.value(num)
void WebAssemblyGlobalSetValue(
    const v8::FunctionCallbackInfo<v8::Value>& args) {
  v8::Isolate* isolate = args.GetIsolate();
  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
  HandleScope scope(isolate);
  Local<Context> context = isolate->GetCurrentContext();
  ScheduledErrorThrower thrower(i_isolate, "set WebAssembly.Global.value");
  EXTRACT_THIS(receiver, WasmGlobalObject);

  if (!receiver->is_mutable()) {
    thrower.TypeError("Can't set the value of an immutable global.");
    return;
  }
  if (args[0]->IsUndefined()) {
    thrower.TypeError("Argument 0 is required");
    return;
  }

  switch (receiver->type().kind()) {
    case i::wasm::ValueType::kI32: {
      int32_t i32_value = 0;
      if (!args[0]->Int32Value(context).To(&i32_value)) return;
      receiver->SetI32(i32_value);
      break;
    }
    case i::wasm::ValueType::kI64: {
      auto enabled_features = i::wasm::WasmFeatures::FromIsolate(i_isolate);
      if (enabled_features.has_bigint()) {
        v8::Local<v8::BigInt> bigint_value;
        if (!args[0]->ToBigInt(context).ToLocal(&bigint_value)) return;
        receiver->SetI64(bigint_value->Int64Value());
      } else {
        thrower.TypeError("Can't set the value of i64 WebAssembly.Global");
      }
      break;
    }
    case i::wasm::ValueType::kF32: {
      double f64_value = 0;
      if (!args[0]->NumberValue(context).To(&f64_value)) return;
      receiver->SetF32(i::DoubleToFloat32(f64_value));
      break;
    }
    case i::wasm::ValueType::kF64: {
      double f64_value = 0;
      if (!args[0]->NumberValue(context).To(&f64_value)) return;
      receiver->SetF64(f64_value);
      break;
    }
    case i::wasm::ValueType::kS128:
      thrower.TypeError("Can't set the value of s128 WebAssembly.Global");
      break;
    case i::wasm::ValueType::kRef:
    case i::wasm::ValueType::kOptRef:
      switch (receiver->type().heap_representation()) {
        case i::wasm::HeapType::kExtern:
        case i::wasm::HeapType::kExn:
          receiver->SetExternRef(Utils::OpenHandle(*args[0]));
          break;
        case i::wasm::HeapType::kFunc: {
          if (!receiver->SetFuncRef(i_isolate, Utils::OpenHandle(*args[0]))) {
            thrower.TypeError(
                "value of an funcref reference must be either null or an "
                "exported function");
          }
          break;
        }

        case i::wasm::HeapType::kEq:
        default:
          // TODO(7748): Implement these.
          UNIMPLEMENTED();
          break;
      }
      break;
    case i::wasm::ValueType::kRtt:
      // TODO(7748): Implement.
      UNIMPLEMENTED();
      break;
    case i::wasm::ValueType::kI8:
    case i::wasm::ValueType::kI16:
    case i::wasm::ValueType::kBottom:
    case i::wasm::ValueType::kStmt:
      UNREACHABLE();
  }
}

// WebAssembly.Global.type(WebAssembly.Global) -> GlobalType
void WebAssemblyGlobalType(const v8::FunctionCallbackInfo<v8::Value>& args) {
  v8::Isolate* isolate = args.GetIsolate();
  HandleScope scope(isolate);
  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
  ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Global.type()");

  auto maybe_global = GetFirstArgumentAsGlobal(args, &thrower);
  if (thrower.error()) return;
  i::Handle<i::WasmGlobalObject> global = maybe_global.ToHandleChecked();
  auto type = i::wasm::GetTypeForGlobal(i_isolate, global->is_mutable(),
                                        global->type());
  args.GetReturnValue().Set(Utils::ToLocal(type));
}

}  // namespace

// TODO(titzer): we use the API to create the function template because the
// internal guts are too ugly to replicate here.
static i::Handle<i::FunctionTemplateInfo> NewFunctionTemplate(
    i::Isolate* i_isolate, FunctionCallback func, bool has_prototype) {
  Isolate* isolate = reinterpret_cast<Isolate*>(i_isolate);
  Local<FunctionTemplate> templ = FunctionTemplate::New(isolate, func);
  has_prototype ? templ->ReadOnlyPrototype() : templ->RemovePrototype();
  return v8::Utils::OpenHandle(*templ);
}

static i::Handle<i::ObjectTemplateInfo> NewObjectTemplate(
    i::Isolate* i_isolate) {
  Isolate* isolate = reinterpret_cast<Isolate*>(i_isolate);
  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
  return v8::Utils::OpenHandle(*templ);
}

namespace internal {

Handle<JSFunction> CreateFunc(Isolate* isolate, Handle<String> name,
                              FunctionCallback func, bool has_prototype) {
  Handle<FunctionTemplateInfo> temp =
      NewFunctionTemplate(isolate, func, has_prototype);
  Handle<JSFunction> function =
      ApiNatives::InstantiateFunction(temp, name).ToHandleChecked();
  DCHECK(function->shared().HasSharedName());
  return function;
}

Handle<JSFunction> InstallFunc(Isolate* isolate, Handle<JSObject> object,
                               const char* str, FunctionCallback func,
                               int length, bool has_prototype = false,
                               PropertyAttributes attributes = NONE) {
  Handle<String> name = v8_str(isolate, str);
  Handle<JSFunction> function = CreateFunc(isolate, name, func, has_prototype);
  function->shared().set_length(length);
  JSObject::AddProperty(isolate, object, name, function, attributes);
  return function;
}

Handle<JSFunction> InstallConstructorFunc(Isolate* isolate,
                                          Handle<JSObject> object,
                                          const char* str,
                                          FunctionCallback func) {
  return InstallFunc(isolate, object, str, func, 1, true, DONT_ENUM);
}

Handle<String> GetterName(Isolate* isolate, Handle<String> name) {
  return Name::ToFunctionName(isolate, name, isolate->factory()->get_string())
      .ToHandleChecked();
}

void InstallGetter(Isolate* isolate, Handle<JSObject> object, const char* str,
                   FunctionCallback func) {
  Handle<String> name = v8_str(isolate, str);
  Handle<JSFunction> function =
      CreateFunc(isolate, GetterName(isolate, name), func, false);

  Utils::ToLocal(object)->SetAccessorProperty(Utils::ToLocal(name),
                                              Utils::ToLocal(function),
                                              Local<Function>(), v8::None);
}

Handle<String> SetterName(Isolate* isolate, Handle<String> name) {
  return Name::ToFunctionName(isolate, name, isolate->factory()->set_string())
      .ToHandleChecked();
}

void InstallGetterSetter(Isolate* isolate, Handle<JSObject> object,
                         const char* str, FunctionCallback getter,
                         FunctionCallback setter) {
  Handle<String> name = v8_str(isolate, str);
  Handle<JSFunction> getter_func =
      CreateFunc(isolate, GetterName(isolate, name), getter, false);
  Handle<JSFunction> setter_func =
      CreateFunc(isolate, SetterName(isolate, name), setter, false);
  setter_func->shared().set_length(1);

  Utils::ToLocal(object)->SetAccessorProperty(
      Utils::ToLocal(name), Utils::ToLocal(getter_func),
      Utils::ToLocal(setter_func), v8::None);
}

// Assigns a dummy instance template to the given constructor function. Used to
// make sure the implicit receivers for the constructors in this file have an
// instance type different from the internal one, they allocate the resulting
// object explicitly and ignore implicit receiver.
void SetDummyInstanceTemplate(Isolate* isolate, Handle<JSFunction> fun) {
  Handle<ObjectTemplateInfo> instance_template = NewObjectTemplate(isolate);
  FunctionTemplateInfo::SetInstanceTemplate(
      isolate, handle(fun->shared().get_api_func_data(), isolate),
      instance_template);
}

// static
void WasmJs::Install(Isolate* isolate, bool exposed_on_global_object) {
  Handle<JSGlobalObject> global = isolate->global_object();
  Handle<Context> context(global->native_context(), isolate);
  // Install the JS API once only.
  Object prev = context->get(Context::WASM_MODULE_CONSTRUCTOR_INDEX);
  if (!prev.IsUndefined(isolate)) {
    DCHECK(prev.IsJSFunction());
    return;
  }

  Factory* factory = isolate->factory();

  // Setup WebAssembly
  Handle<String> name = v8_str(isolate, "WebAssembly");
  NewFunctionArgs args = NewFunctionArgs::ForFunctionWithoutCode(
      name, isolate->strict_function_map(), LanguageMode::kStrict);
  Handle<JSFunction> cons = factory->NewFunction(args);
  JSFunction::SetPrototype(cons, isolate->initial_object_prototype());
  Handle<JSObject> webassembly =
      factory->NewJSObject(cons, AllocationType::kOld);

  PropertyAttributes ro_attributes =
      static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY);
  JSObject::AddProperty(isolate, webassembly, factory->to_string_tag_symbol(),
                        name, ro_attributes);
  InstallFunc(isolate, webassembly, "compile", WebAssemblyCompile, 1);
  InstallFunc(isolate, webassembly, "validate", WebAssemblyValidate, 1);
  InstallFunc(isolate, webassembly, "instantiate", WebAssemblyInstantiate, 1);

  if (FLAG_wasm_test_streaming) {
    isolate->set_wasm_streaming_callback(WasmStreamingCallbackForTesting);
  }

  if (isolate->wasm_streaming_callback() != nullptr) {
    InstallFunc(isolate, webassembly, "compileStreaming",
                WebAssemblyCompileStreaming, 1);
    InstallFunc(isolate, webassembly, "instantiateStreaming",
                WebAssemblyInstantiateStreaming, 1);
  }

  // Expose the API on the global object if configured to do so.
  if (exposed_on_global_object) {
    JSObject::AddProperty(isolate, global, name, webassembly, DONT_ENUM);
  }

  // Setup Module
  Handle<JSFunction> module_constructor =
      InstallConstructorFunc(isolate, webassembly, "Module", WebAssemblyModule);
  context->set_wasm_module_constructor(*module_constructor);
  SetDummyInstanceTemplate(isolate, module_constructor);
  JSFunction::EnsureHasInitialMap(module_constructor);
  Handle<JSObject> module_proto(
      JSObject::cast(module_constructor->instance_prototype()), isolate);
  Handle<Map> module_map = isolate->factory()->NewMap(
      i::WASM_MODULE_OBJECT_TYPE, WasmModuleObject::kHeaderSize);
  JSFunction::SetInitialMap(module_constructor, module_map, module_proto);
  InstallFunc(isolate, module_constructor, "imports", WebAssemblyModuleImports,
              1);
  InstallFunc(isolate, module_constructor, "exports", WebAssemblyModuleExports,
              1);
  InstallFunc(isolate, module_constructor, "customSections",
              WebAssemblyModuleCustomSections, 2);
  JSObject::AddProperty(isolate, module_proto, factory->to_string_tag_symbol(),
                        v8_str(isolate, "WebAssembly.Module"), ro_attributes);

  // Setup Instance
  Handle<JSFunction> instance_constructor = InstallConstructorFunc(
      isolate, webassembly, "Instance", WebAssemblyInstance);
  context->set_wasm_instance_constructor(*instance_constructor);
  SetDummyInstanceTemplate(isolate, instance_constructor);
  JSFunction::EnsureHasInitialMap(instance_constructor);
  Handle<JSObject> instance_proto(
      JSObject::cast(instance_constructor->instance_prototype()), isolate);
  Handle<Map> instance_map = isolate->factory()->NewMap(
      i::WASM_INSTANCE_OBJECT_TYPE, WasmInstanceObject::kHeaderSize);
  JSFunction::SetInitialMap(instance_constructor, instance_map, instance_proto);
  InstallGetter(isolate, instance_proto, "exports",
                WebAssemblyInstanceGetExports);
  JSObject::AddProperty(isolate, instance_proto,
                        factory->to_string_tag_symbol(),
                        v8_str(isolate, "WebAssembly.Instance"), ro_attributes);

  // The context is not set up completely yet. That's why we cannot use
  // {WasmFeatures::FromIsolate} and have to use {WasmFeatures::FromFlags}
  // instead.
  auto enabled_features = i::wasm::WasmFeatures::FromFlags();

  // Setup Table
  Handle<JSFunction> table_constructor =
      InstallConstructorFunc(isolate, webassembly, "Table", WebAssemblyTable);
  context->set_wasm_table_constructor(*table_constructor);
  SetDummyInstanceTemplate(isolate, table_constructor);
  JSFunction::EnsureHasInitialMap(table_constructor);
  Handle<JSObject> table_proto(
      JSObject::cast(table_constructor->instance_prototype()), isolate);
  Handle<Map> table_map = isolate->factory()->NewMap(
      i::WASM_TABLE_OBJECT_TYPE, WasmTableObject::kHeaderSize);
  JSFunction::SetInitialMap(table_constructor, table_map, table_proto);
  InstallGetter(isolate, table_proto, "length", WebAssemblyTableGetLength);
  InstallFunc(isolate, table_proto, "grow", WebAssemblyTableGrow, 1);
  InstallFunc(isolate, table_proto, "get", WebAssemblyTableGet, 1);
  InstallFunc(isolate, table_proto, "set", WebAssemblyTableSet, 2);
  if (enabled_features.has_type_reflection()) {
    InstallFunc(isolate, table_constructor, "type", WebAssemblyTableType, 1);
  }
  JSObject::AddProperty(isolate, table_proto, factory->to_string_tag_symbol(),
                        v8_str(isolate, "WebAssembly.Table"), ro_attributes);

  // Setup Memory
  // Enables shared memory support.
  i::FLAG_experimental_wasm_threads = true;
  i::FLAG_experimental_wasm_simd = true;
  Handle<JSFunction> memory_constructor =
      InstallConstructorFunc(isolate, webassembly, "Memory", WebAssemblyMemory);
  context->set_wasm_memory_constructor(*memory_constructor);
  SetDummyInstanceTemplate(isolate, memory_constructor);
  JSFunction::EnsureHasInitialMap(memory_constructor);
  Handle<JSObject> memory_proto(
      JSObject::cast(memory_constructor->instance_prototype()), isolate);
  Handle<Map> memory_map = isolate->factory()->NewMap(
      i::WASM_MEMORY_OBJECT_TYPE, WasmMemoryObject::kHeaderSize);
  JSFunction::SetInitialMap(memory_constructor, memory_map, memory_proto);
  InstallFunc(isolate, memory_proto, "grow", WebAssemblyMemoryGrow, 1);
  InstallGetter(isolate, memory_proto, "buffer", WebAssemblyMemoryGetBuffer);
  if (enabled_features.has_type_reflection()) {
    InstallFunc(isolate, memory_constructor, "type", WebAssemblyMemoryType, 1);
  }
  JSObject::AddProperty(isolate, memory_proto, factory->to_string_tag_symbol(),
                        v8_str(isolate, "WebAssembly.Memory"), ro_attributes);

  // Setup Global
  Handle<JSFunction> global_constructor =
      InstallConstructorFunc(isolate, webassembly, "Global", WebAssemblyGlobal);
  context->set_wasm_global_constructor(*global_constructor);
  SetDummyInstanceTemplate(isolate, global_constructor);
  JSFunction::EnsureHasInitialMap(global_constructor);
  Handle<JSObject> global_proto(
      JSObject::cast(global_constructor->instance_prototype()), isolate);
  Handle<Map> global_map = isolate->factory()->NewMap(
      i::WASM_GLOBAL_OBJECT_TYPE, WasmGlobalObject::kHeaderSize);
  JSFunction::SetInitialMap(global_constructor, global_map, global_proto);
  InstallFunc(isolate, global_proto, "valueOf", WebAssemblyGlobalValueOf, 0);
  InstallGetterSetter(isolate, global_proto, "value", WebAssemblyGlobalGetValue,
                      WebAssemblyGlobalSetValue);
  if (enabled_features.has_type_reflection()) {
    InstallFunc(isolate, global_constructor, "type", WebAssemblyGlobalType, 1);
  }
  JSObject::AddProperty(isolate, global_proto, factory->to_string_tag_symbol(),
                        v8_str(isolate, "WebAssembly.Global"), ro_attributes);

  // Setup Exception
  if (enabled_features.has_eh()) {
    Handle<JSFunction> exception_constructor = InstallConstructorFunc(
        isolate, webassembly, "Exception", WebAssemblyException);
    context->set_wasm_exception_constructor(*exception_constructor);
    SetDummyInstanceTemplate(isolate, exception_constructor);
    JSFunction::EnsureHasInitialMap(exception_constructor);
    Handle<JSObject> exception_proto(
        JSObject::cast(exception_constructor->instance_prototype()), isolate);
    Handle<Map> exception_map = isolate->factory()->NewMap(
        i::WASM_EXCEPTION_OBJECT_TYPE, WasmExceptionObject::kHeaderSize);
    JSFunction::SetInitialMap(exception_constructor, exception_map,
                              exception_proto);
  }

  // Setup Function
  if (enabled_features.has_type_reflection()) {
    Handle<JSFunction> function_constructor = InstallConstructorFunc(
        isolate, webassembly, "Function", WebAssemblyFunction);
    SetDummyInstanceTemplate(isolate, function_constructor);
    JSFunction::EnsureHasInitialMap(function_constructor);
    Handle<JSObject> function_proto(
        JSObject::cast(function_constructor->instance_prototype()), isolate);
    Handle<Map> function_map = isolate->factory()->CreateSloppyFunctionMap(
        FUNCTION_WITHOUT_PROTOTYPE, MaybeHandle<JSFunction>());
    CHECK(JSObject::SetPrototype(
              function_proto,
              handle(context->function_function().prototype(), isolate), false,
              kDontThrow)
              .FromJust());
    JSFunction::SetInitialMap(function_constructor, function_map,
                              function_proto);
    InstallFunc(isolate, function_constructor, "type", WebAssemblyFunctionType,
                1);
    // Make all exported functions an instance of {WebAssembly.Function}.
    context->set_wasm_exported_function_map(*function_map);
  } else {
    // Make all exported functions an instance of {Function}.
    Handle<Map> function_map = isolate->sloppy_function_without_prototype_map();
    context->set_wasm_exported_function_map(*function_map);
  }

  // Setup errors
  Handle<JSFunction> compile_error(
      isolate->native_context()->wasm_compile_error_function(), isolate);
  JSObject::AddProperty(isolate, webassembly,
                        isolate->factory()->CompileError_string(),
                        compile_error, DONT_ENUM);
  Handle<JSFunction> link_error(
      isolate->native_context()->wasm_link_error_function(), isolate);
  JSObject::AddProperty(isolate, webassembly,
                        isolate->factory()->LinkError_string(), link_error,
                        DONT_ENUM);
  Handle<JSFunction> runtime_error(
      isolate->native_context()->wasm_runtime_error_function(), isolate);
  JSObject::AddProperty(isolate, webassembly,
                        isolate->factory()->RuntimeError_string(),
                        runtime_error, DONT_ENUM);
}

namespace {
void SetMapValue(Isolate* isolate, Handle<JSMap> map, Handle<Object> key,
                 Handle<Object> value) {
  DCHECK(!map.is_null() && !key.is_null() && !value.is_null());
  Handle<Object> argv[] = {key, value};
  Execution::CallBuiltin(isolate, isolate->map_set(), map, arraysize(argv),
                         argv)
      .Check();
}

Handle<Object> GetMapValue(Isolate* isolate, Handle<JSMap> map,
                           Handle<Object> key) {
  DCHECK(!map.is_null() && !key.is_null());
  Handle<Object> argv[] = {key};
  return Execution::CallBuiltin(isolate, isolate->map_get(), map,
                                arraysize(argv), argv)
      .ToHandleChecked();
}

// Look up a name in a name table. Name tables are stored under the "names"
// property of the handler and map names to index.
base::Optional<int> ResolveValueSelector(Isolate* isolate,
                                         Handle<Name> property,
                                         Handle<JSObject> handler,
                                         bool enable_index_lookup) {
  size_t index = 0;
  if (enable_index_lookup && property->AsIntegerIndex(&index) &&
      index < kMaxInt) {
    return static_cast<int>(index);
  }

  Handle<Object> name_table =
      JSObject::GetProperty(isolate, handler, "names").ToHandleChecked();
  DCHECK(name_table->IsJSMap());

  Handle<Object> object =
      GetMapValue(isolate, Handle<JSMap>::cast(name_table), property);
  if (object->IsUndefined()) return {};
  DCHECK(object->IsNumeric());
  return NumberToInt32(*object);
}

// Helper for unpacking a maybe name that makes a default with an index if
// the name is empty. If the name is not empty, it's prefixed with a $.
Handle<String> GetNameOrDefault(Isolate* isolate,
                                MaybeHandle<String> maybe_name,
                                const char* default_name_prefix, int index) {
  Handle<String> name;
  if (maybe_name.ToHandle(&name)) {
    return isolate->factory()
        ->NewConsString(isolate->factory()->NewStringFromAsciiChecked("$"),
                        name)
        .ToHandleChecked();
  }

  // Maximum length of the default names: $memory-2147483648\0
  static constexpr int kMaxStrLen = 19;
  EmbeddedVector<char, kMaxStrLen> value;
  DCHECK_LT(strlen(default_name_prefix) + /*strlen(kMinInt)*/ 11, kMaxStrLen);
  int len = SNPrintF(value, "%s%d", default_name_prefix, index);
  return isolate->factory()->InternalizeString(value.SubVector(0, len));
}

// Generate names for the locals. Names either come from the name table,
// otherwise the default $varX is used.
std::vector<Handle<String>> GetLocalNames(Handle<WasmInstanceObject> instance,
                                          Address pc) {
  wasm::NativeModule* native_module = instance->module_object().native_module();
  wasm::DebugInfo* debug_info = native_module->GetDebugInfo();
  int num_locals = debug_info->GetNumLocals(pc);
  auto* isolate = instance->GetIsolate();

  wasm::ModuleWireBytes module_wire_bytes(
      instance->module_object().native_module()->wire_bytes());
  const wasm::WasmFunction& function = debug_info->GetFunctionAtAddress(pc);

  std::vector<Handle<String>> names;
  for (int i = 0; i < num_locals; ++i) {
    wasm::WireBytesRef local_name_ref =
        debug_info->GetLocalName(function.func_index, i);
    DCHECK(module_wire_bytes.BoundsCheck(local_name_ref));
    Vector<const char> name_vec =
        module_wire_bytes.GetNameOrNull(local_name_ref);
    names.emplace_back(GetNameOrDefault(
        isolate,
        name_vec.empty() ? MaybeHandle<String>()
                         : isolate->factory()->NewStringFromUtf8(name_vec),
        "$var", i));
  }

  return names;
}

// Generate names for the globals. Names either come from the name table,
// otherwise the default $globalX is used.
std::vector<Handle<String>> GetGlobalNames(
    Handle<WasmInstanceObject> instance) {
  Isolate* isolate = instance->GetIsolate();
  auto& globals = instance->module()->globals;
  std::vector<Handle<String>> names;
  for (uint32_t i = 0; i < globals.size(); ++i) {
    names.emplace_back(GetNameOrDefault(
        isolate, WasmInstanceObject::GetGlobalNameOrNull(isolate, instance, i),
        "$global", i));
  }
  return names;
}

// Generate names for the functions.
std::vector<Handle<String>> GetFunctionNames(
    Handle<WasmInstanceObject> instance) {
  Isolate* isolate = instance->GetIsolate();
  auto* module = instance->module();

  wasm::ModuleWireBytes wire_bytes(
      instance->module_object().native_module()->wire_bytes());

  std::vector<Handle<String>> names;
  for (auto& function : module->functions) {
    DCHECK_EQ(function.func_index, names.size());
    wasm::WireBytesRef name_ref =
        module->lazily_generated_names.LookupFunctionName(
            wire_bytes, function.func_index, VectorOf(module->export_table));
    DCHECK(wire_bytes.BoundsCheck(name_ref));
    Vector<const char> name_vec = wire_bytes.GetNameOrNull(name_ref);
    names.emplace_back(GetNameOrDefault(
        isolate,
        name_vec.empty() ? MaybeHandle<String>()
                         : isolate->factory()->NewStringFromUtf8(name_vec),
        "$func", function.func_index));
  }

  return names;
}

// Generate names for the imports.
std::vector<Handle<String>> GetImportNames(
    Handle<WasmInstanceObject> instance) {
  Isolate* isolate = instance->GetIsolate();
  const wasm::WasmModule* module = instance->module();
  Handle<WasmModuleObject> module_object(instance->module_object(), isolate);
  int num_imports = static_cast<int>(module->import_table.size());

  std::vector<Handle<String>> names;
  for (int index = 0; index < num_imports; ++index) {
    const wasm::WasmImport& import = module->import_table[index];

    names.emplace_back(WasmModuleObject::ExtractUtf8StringFromModuleBytes(
        isolate, module_object, import.field_name, kInternalize));
  }

  return names;
}

// Generate names for the memories.
std::vector<Handle<String>> GetMemoryNames(
    Handle<WasmInstanceObject> instance) {
  Isolate* isolate = instance->GetIsolate();

  std::vector<Handle<String>> names;
  uint32_t memory_count = instance->has_memory_object() ? 1 : 0;
  for (uint32_t memory_index = 0; memory_index < memory_count; ++memory_index) {
    names.emplace_back(GetNameOrDefault(isolate,
                                        WasmInstanceObject::GetMemoryNameOrNull(
                                            isolate, instance, memory_index),
                                        "$memory", memory_index));
  }

  return names;
}

// Generate names for the tables.
std::vector<Handle<String>> GetTableNames(Handle<WasmInstanceObject> instance) {
  Isolate* isolate = instance->GetIsolate();
  auto tables = handle(instance->tables(), isolate);

  std::vector<Handle<String>> names;
  for (int table_index = 0; table_index < tables->length(); ++table_index) {
    auto func_table =
        handle(WasmTableObject::cast(tables->get(table_index)), isolate);
    if (!func_table->type().is_reference_to(wasm::HeapType::kFunc)) continue;

    names.emplace_back(GetNameOrDefault(
        isolate,
        WasmInstanceObject::GetTableNameOrNull(isolate, instance, table_index),
        "$table", table_index));
  }
  return names;
}

// Generate names for the exports
std::vector<Handle<String>> GetExportNames(
    Handle<WasmInstanceObject> instance) {
  Isolate* isolate = instance->GetIsolate();
  const wasm::WasmModule* module = instance->module();
  Handle<WasmModuleObject> module_object(instance->module_object(), isolate);
  int num_exports = static_cast<int>(module->export_table.size());

  std::vector<Handle<String>> names;

  for (int index = 0; index < num_exports; ++index) {
    const wasm::WasmExport& exp = module->export_table[index];

    names.emplace_back(WasmModuleObject::ExtractUtf8StringFromModuleBytes(
        isolate, module_object, exp.name, kInternalize));
  }
  return names;
}

Handle<WasmInstanceObject> GetInstance(Isolate* isolate,
                                       Handle<JSObject> handler) {
  Handle<Object> instance =
      JSObject::GetProperty(isolate, handler, "instance").ToHandleChecked();
  DCHECK(instance->IsWasmInstanceObject());
  return Handle<WasmInstanceObject>::cast(instance);
}

Address GetPC(Isolate* isolate, Handle<JSObject> handler) {
  Handle<Object> pc =
      JSObject::GetProperty(isolate, handler, "pc").ToHandleChecked();
  DCHECK(pc->IsBigInt());
  return Handle<BigInt>::cast(pc)->AsUint64();
}

Address GetFP(Isolate* isolate, Handle<JSObject> handler) {
  Handle<Object> fp =
      JSObject::GetProperty(isolate, handler, "fp").ToHandleChecked();
  DCHECK(fp->IsBigInt());
  return Handle<BigInt>::cast(fp)->AsUint64();
}

Address GetCalleeFP(Isolate* isolate, Handle<JSObject> handler) {
  Handle<Object> callee_fp =
      JSObject::GetProperty(isolate, handler, "callee_fp").ToHandleChecked();
  DCHECK(callee_fp->IsBigInt());
  return Handle<BigInt>::cast(callee_fp)->AsUint64();
}

// Convert a WasmValue to an appropriate JS representation.
static Handle<Object> WasmValueToObject(Isolate* isolate,
                                        wasm::WasmValue value) {
  auto* factory = isolate->factory();
  switch (value.type().kind()) {
    case wasm::ValueType::kI32:
      return factory->NewNumberFromInt(value.to_i32());
    case wasm::ValueType::kI64:
      return BigInt::FromInt64(isolate, value.to_i64());
    case wasm::ValueType::kF32:
      return factory->NewNumber(value.to_f32());
    case wasm::ValueType::kF64:
      return factory->NewNumber(value.to_f64());
    case wasm::ValueType::kS128: {
      wasm::Simd128 s128 = value.to_s128();
      Handle<JSArrayBuffer> buffer;
      if (!isolate->factory()
               ->NewJSArrayBufferAndBackingStore(
                   kSimd128Size, InitializedFlag::kUninitialized)
               .ToHandle(&buffer)) {
        isolate->FatalProcessOutOfHeapMemory(
            "failed to allocate backing store");
      }

      memcpy(buffer->allocation_base(), s128.bytes(),
                   buffer->byte_length());
      return isolate->factory()->NewJSTypedArray(kExternalUint8Array, buffer, 0,
                                                 buffer->byte_length());
    }
    case wasm::ValueType::kRef:
      return value.to_externref();
    default:
      break;
  }
  return factory->undefined_value();
}

base::Optional<int> HasLocalImpl(Isolate* isolate, Handle<Name> property,
                                 Handle<JSObject> handler,
                                 bool enable_index_lookup) {
  Handle<WasmInstanceObject> instance = GetInstance(isolate, handler);

  base::Optional<int> index =
      ResolveValueSelector(isolate, property, handler, enable_index_lookup);
  if (!index) return index;
  Address pc = GetPC(isolate, handler);

  wasm::DebugInfo* debug_info =
      instance->module_object().native_module()->GetDebugInfo();
  int num_locals = debug_info->GetNumLocals(pc);
  if (0 <= index && index < num_locals) return index;
  return {};
}

Handle<Object> GetLocalImpl(Isolate* isolate, Handle<Name> property,
                            Handle<JSObject> handler,
                            bool enable_index_lookup) {
  Factory* factory = isolate->factory();
  Handle<WasmInstanceObject> instance = GetInstance(isolate, handler);

  base::Optional<int> index =
      HasLocalImpl(isolate, property, handler, enable_index_lookup);
  if (!index) return factory->undefined_value();
  Address pc = GetPC(isolate, handler);
  Address fp = GetFP(isolate, handler);
  Address callee_fp = GetCalleeFP(isolate, handler);

  wasm::DebugInfo* debug_info =
      instance->module_object().native_module()->GetDebugInfo();
  wasm::WasmValue value = debug_info->GetLocalValue(*index, pc, fp, callee_fp);
  return WasmValueToObject(isolate, value);
}

base::Optional<int> HasGlobalImpl(Isolate* isolate, Handle<Name> property,
                                  Handle<JSObject> handler,
                                  bool enable_index_lookup) {
  Handle<WasmInstanceObject> instance = GetInstance(isolate, handler);
  base::Optional<int> index =
      ResolveValueSelector(isolate, property, handler, enable_index_lookup);
  if (!index) return index;

  const std::vector<wasm::WasmGlobal>& globals = instance->module()->globals;
  if (globals.size() <= kMaxInt && 0 <= *index &&
      *index < static_cast<int>(globals.size())) {
    return index;
  }
  return {};
}

Handle<Object> GetGlobalImpl(Isolate* isolate, Handle<Name> property,
                             Handle<JSObject> handler,
                             bool enable_index_lookup) {
  Handle<WasmInstanceObject> instance = GetInstance(isolate, handler);
  base::Optional<int> index =
      HasGlobalImpl(isolate, property, handler, enable_index_lookup);
  if (!index) return isolate->factory()->undefined_value();

  const std::vector<wasm::WasmGlobal>& globals = instance->module()->globals;
  return WasmValueToObject(
      isolate, WasmInstanceObject::GetGlobalValue(instance, globals[*index]));
}

base::Optional<int> HasMemoryImpl(Isolate* isolate, Handle<Name> property,
                                  Handle<JSObject> handler,
                                  bool enable_index_lookup) {
  Handle<WasmInstanceObject> instance = GetInstance(isolate, handler);
  base::Optional<int> index =
      ResolveValueSelector(isolate, property, handler, enable_index_lookup);
  if (index && *index == 0 && instance->has_memory_object()) return index;
  return {};
}

Handle<Object> GetMemoryImpl(Isolate* isolate, Handle<Name> property,
                             Handle<JSObject> handler,
                             bool enable_index_lookup) {
  Handle<WasmInstanceObject> instance = GetInstance(isolate, handler);
  base::Optional<int> index =
      HasMemoryImpl(isolate, property, handler, enable_index_lookup);
  if (index) return handle(instance->memory_object(), isolate);
  return isolate->factory()->undefined_value();
}

base::Optional<int> HasFunctionImpl(Isolate* isolate, Handle<Name> property,
                                    Handle<JSObject> handler,
                                    bool enable_index_lookup) {
  Handle<WasmInstanceObject> instance = GetInstance(isolate, handler);
  base::Optional<int> index =
      ResolveValueSelector(isolate, property, handler, enable_index_lookup);
  if (!index) return index;
  const std::vector<wasm::WasmFunction>& functions =
      instance->module()->functions;
  if (functions.size() <= kMaxInt && 0 <= *index &&
      *index < static_cast<int>(functions.size())) {
    return index;
  }
  return {};
}

Handle<Object> GetFunctionImpl(Isolate* isolate, Handle<Name> property,
                               Handle<JSObject> handler,
                               bool enable_index_lookup) {
  Handle<WasmInstanceObject> instance = GetInstance(isolate, handler);
  base::Optional<int> index =
      HasFunctionImpl(isolate, property, handler, enable_index_lookup);
  if (!index) return isolate->factory()->undefined_value();

  return WasmInstanceObject::GetOrCreateWasmExternalFunction(isolate, instance,
                                                             *index);
}

base::Optional<int> HasTableImpl(Isolate* isolate, Handle<Name> property,
                                 Handle<JSObject> handler,
                                 bool enable_index_lookup) {
  Handle<WasmInstanceObject> instance = GetInstance(isolate, handler);
  base::Optional<int> index =
      ResolveValueSelector(isolate, property, handler, enable_index_lookup);
  if (!index) return index;
  Handle<FixedArray> tables(instance->tables(), isolate);
  int num_tables = tables->length();
  if (*index < 0 || *index >= num_tables) return {};

  Handle<WasmTableObject> func_table(WasmTableObject::cast(tables->get(*index)),
                                     isolate);
  if (func_table->type().is_reference_to(wasm::HeapType::kFunc)) return index;
  return {};
}

Handle<Object> GetTableImpl(Isolate* isolate, Handle<Name> property,
                            Handle<JSObject> handler,
                            bool enable_index_lookup) {
  Handle<WasmInstanceObject> instance = GetInstance(isolate, handler);
  base::Optional<int> index =
      HasTableImpl(isolate, property, handler, enable_index_lookup);
  if (!index) return isolate->factory()->undefined_value();

  Handle<WasmTableObject> func_table(
      WasmTableObject::cast(instance->tables().get(*index)), isolate);
  return func_table;
}

base::Optional<int> HasImportImpl(Isolate* isolate, Handle<Name> property,
                                  Handle<JSObject> handler,
                                  bool enable_index_lookup) {
  Handle<WasmInstanceObject> instance = GetInstance(isolate, handler);
  base::Optional<int> index =
      ResolveValueSelector(isolate, property, handler, enable_index_lookup);
  if (!index) return index;
  const wasm::WasmModule* module = instance->module();
  Handle<WasmModuleObject> module_object(instance->module_object(), isolate);
  int num_imports = static_cast<int>(module->import_table.size());
  if (0 <= *index && *index < num_imports) return index;
  return {};
}

Handle<JSObject> GetExternalObject(Isolate* isolate,
                                   wasm::ImportExportKindCode kind,
                                   uint32_t index) {
  Handle<JSObject> result = isolate->factory()->NewJSObjectWithNullProto();
  Handle<Object> value = isolate->factory()->NewNumberFromUint(index);
  switch (kind) {
    case wasm::kExternalFunction:
      JSObject::AddProperty(isolate, result, "func", value, NONE);
      break;
    case wasm::kExternalGlobal:
      JSObject::AddProperty(isolate, result, "global", value, NONE);
      break;
    case wasm::kExternalTable:
      JSObject::AddProperty(isolate, result, "table", value, NONE);
      break;
    case wasm::kExternalMemory:
      JSObject::AddProperty(isolate, result, "mem", value, NONE);
      break;
    case wasm::kExternalException:
      JSObject::AddProperty(isolate, result, "exn", value, NONE);
      break;
  }
  return result;
}

Handle<Object> GetImportImpl(Isolate* isolate, Handle<Name> property,
                             Handle<JSObject> handler,
                             bool enable_index_lookup) {
  Handle<WasmInstanceObject> instance = GetInstance(isolate, handler);
  base::Optional<int> index =
      HasImportImpl(isolate, property, handler, enable_index_lookup);
  if (!index) return isolate->factory()->undefined_value();

  const wasm::WasmImport& imp = instance->module()->import_table[*index];
  return GetExternalObject(isolate, imp.kind, imp.index);
}

base::Optional<int> HasExportImpl(Isolate* isolate, Handle<Name> property,
                                  Handle<JSObject> handler,
                                  bool enable_index_lookup) {
  Handle<WasmInstanceObject> instance = GetInstance(isolate, handler);
  base::Optional<int> index =
      ResolveValueSelector(isolate, property, handler, enable_index_lookup);
  if (!index) return index;

  const wasm::WasmModule* module = instance->module();
  Handle<WasmModuleObject> module_object(instance->module_object(), isolate);
  int num_exports = static_cast<int>(module->export_table.size());
  if (0 <= *index && *index < num_exports) return index;
  return {};
}

Handle<Object> GetExportImpl(Isolate* isolate, Handle<Name> property,
                             Handle<JSObject> handler,
                             bool enable_index_lookup) {
  Handle<WasmInstanceObject> instance = GetInstance(isolate, handler);
  base::Optional<int> index =
      HasExportImpl(isolate, property, handler, enable_index_lookup);
  if (!index) return isolate->factory()->undefined_value();

  const wasm::WasmExport& exp = instance->module()->export_table[*index];
  return GetExternalObject(isolate, exp.kind, exp.index);
}

// Generic has trap callback for the index space proxies.
template <base::Optional<int> Impl(Isolate*, Handle<Name>, Handle<JSObject>,
                                   bool)>
void HasTrapCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
  DCHECK_GE(args.Length(), 2);
  Isolate* isolate = reinterpret_cast<Isolate*>(args.GetIsolate());
  DCHECK(args.This()->IsObject());
  Handle<JSObject> handler =
      Handle<JSObject>::cast(Utils::OpenHandle(*args.This()));

  DCHECK(args[1]->IsName());
  Handle<Name> property = Handle<Name>::cast(Utils::OpenHandle(*args[1]));
  args.GetReturnValue().Set(Impl(isolate, property, handler, true).has_value());
}

// Generic get trap callback for the index space proxies.
template <Handle<Object> Impl(Isolate*, Handle<Name>, Handle<JSObject>, bool)>
void GetTrapCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
  DCHECK_GE(args.Length(), 2);
  Isolate* isolate = reinterpret_cast<Isolate*>(args.GetIsolate());
  DCHECK(args.This()->IsObject());
  Handle<JSObject> handler =
      Handle<JSObject>::cast(Utils::OpenHandle(*args.This()));

  DCHECK(args[1]->IsName());
  Handle<Name> property = Handle<Name>::cast(Utils::OpenHandle(*args[1]));
  args.GetReturnValue().Set(
      Utils::ToLocal(Impl(isolate, property, handler, true)));
}

template <typename ReturnT>
ReturnT DelegateToplevelCall(Isolate* isolate, Handle<JSObject> target,
                             Handle<Name> property, const char* index_space,
                             ReturnT (*impl)(Isolate*, Handle<Name>,
                                             Handle<JSObject>, bool)) {
  Handle<Object> namespace_proxy =
      JSObject::GetProperty(isolate, target, index_space).ToHandleChecked();
  DCHECK(namespace_proxy->IsJSProxy());
  Handle<JSObject> namespace_handler(
      JSObject::cast(Handle<JSProxy>::cast(namespace_proxy)->handler()),
      isolate);
  return impl(isolate, property, namespace_handler, false);
}

template <typename ReturnT>
using DelegateCallback = ReturnT (*)(Isolate*, Handle<Name>, Handle<JSObject>,
                                     bool);

// Has trap callback for the top-level proxy.
void ToplevelHasTrapCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
  DCHECK_GE(args.Length(), 2);
  Isolate* isolate = reinterpret_cast<Isolate*>(args.GetIsolate());
  DCHECK(args[0]->IsObject());
  Handle<JSObject> target = Handle<JSObject>::cast(Utils::OpenHandle(*args[0]));

  DCHECK(args[1]->IsName());
  Handle<Name> property = Handle<Name>::cast(Utils::OpenHandle(*args[1]));

  // First check if the property exists on the target.
  if (JSObject::HasProperty(target, property).FromMaybe(false)) {
    args.GetReturnValue().Set(true);
    return;
  }

  // Now check the index space proxies in order if they know the property.
  constexpr std::pair<const char*, DelegateCallback<base::Optional<int>>>
      kDelegates[] = {{"memories", HasMemoryImpl},
                      {"locals", HasLocalImpl},
                      {"tables", HasTableImpl},
                      {"functions", HasFunctionImpl},
                      {"globals", HasGlobalImpl}};
  for (auto& delegate : kDelegates) {
    if (DelegateToplevelCall(isolate, target, property, delegate.first,
                             delegate.second)) {
      args.GetReturnValue().Set(true);
      return;
    }
    args.GetReturnValue().Set(false);
  }
}

// Get trap callback for the top-level proxy.
void ToplevelGetTrapCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
  DCHECK_GE(args.Length(), 2);
  Isolate* isolate = reinterpret_cast<Isolate*>(args.GetIsolate());
  DCHECK(args[0]->IsObject());
  Handle<JSObject> target = Handle<JSObject>::cast(Utils::OpenHandle(*args[0]));

  DCHECK(args[1]->IsName());
  Handle<Name> property = Handle<Name>::cast(Utils::OpenHandle(*args[1]));

  // First, check if the property is a proper property on the target. If so,
  // return its value.
  Handle<Object> value =
      JSObject::GetProperty(isolate, target, property).ToHandleChecked();
  if (!value->IsUndefined()) {
    args.GetReturnValue().Set(Utils::ToLocal(value));
    return;
  }

  // Try the index space proxies in the correct disambiguation order.
  constexpr std::pair<const char*, DelegateCallback<Handle<Object>>>
      kDelegates[] = {{"memories", GetMemoryImpl},
                      {"locals", GetLocalImpl},
                      {"tables", GetTableImpl},
                      {"functions", GetFunctionImpl},
                      {"globals", GetGlobalImpl}};
  for (auto& delegate : kDelegates) {
    value = DelegateToplevelCall(isolate, target, property, delegate.first,
                                 delegate.second);
    if (!value->IsUndefined()) {
      args.GetReturnValue().Set(Utils::ToLocal(value));
      return;
    }
  }
}

// Populate a JSMap with name->index mappings from an ordered list of names.
Handle<JSMap> GetNameTable(Isolate* isolate,
                           const std::vector<Handle<String>>& names) {
  Factory* factory = isolate->factory();
  Handle<JSMap> name_table = factory->NewJSMap();

  for (size_t i = 0; i < names.size(); ++i) {
    SetMapValue(isolate, name_table, names[i], factory->NewNumberFromInt64(i));
  }
  return name_table;
}

// Produce a JSProxy with a given name table and get and has trap handlers.
Handle<JSProxy> GetJSProxy(
    WasmFrame* frame, Handle<JSMap> name_table,
    void (*get_callback)(const v8::FunctionCallbackInfo<v8::Value>&),
    void (*has_callback)(const v8::FunctionCallbackInfo<v8::Value>&)) {
  Isolate* isolate = frame->isolate();
  Factory* factory = isolate->factory();
  Handle<JSObject> target = factory->NewJSObjectWithNullProto();
  Handle<JSObject> handler = factory->NewJSObjectWithNullProto();

  // Besides the name table, the get and has traps need access to the instance
  // and frame information.
  JSObject::AddProperty(isolate, handler, "names", name_table, DONT_ENUM);
  Handle<WasmInstanceObject> instance(frame->wasm_instance(), isolate);
  JSObject::AddProperty(isolate, handler, "instance", instance, DONT_ENUM);
  Handle<BigInt> pc = BigInt::FromInt64(isolate, frame->pc());
  JSObject::AddProperty(isolate, handler, "pc", pc, DONT_ENUM);
  Handle<BigInt> fp = BigInt::FromInt64(isolate, frame->fp());
  JSObject::AddProperty(isolate, handler, "fp", fp, DONT_ENUM);
  Handle<BigInt> callee_fp = BigInt::FromInt64(isolate, frame->callee_fp());
  JSObject::AddProperty(isolate, handler, "callee_fp", callee_fp, DONT_ENUM);

  InstallFunc(isolate, handler, "get", get_callback, 3, false, READ_ONLY);
  InstallFunc(isolate, handler, "has", has_callback, 2, false, READ_ONLY);

  return factory->NewJSProxy(target, handler);
}

Handle<JSObject> GetStackObject(WasmFrame* frame) {
  Isolate* isolate = frame->isolate();
  Handle<JSObject> object = isolate->factory()->NewJSObjectWithNullProto();
  wasm::DebugInfo* debug_info =
      frame->wasm_instance().module_object().native_module()->GetDebugInfo();
  int num_values = debug_info->GetStackDepth(frame->pc());
  for (int i = 0; i < num_values; ++i) {
    wasm::WasmValue value = debug_info->GetStackValue(
        i, frame->pc(), frame->fp(), frame->callee_fp());
    JSObject::AddDataElement(object, i, WasmValueToObject(isolate, value),
                             NONE);
  }
  return object;
}
}  // namespace

// This function generates the JS debug proxy for a given Wasm frame. The debug
// proxy is used when evaluating debug JS expressions on a wasm frame and let's
// the developer inspect the engine state from JS. The proxy provides the
// following interface:
//
// type WasmSimdValue = Uint8Array;
// type WasmValue = number | bigint | object | WasmSimdValue;
// type WasmFunction = (... args : WasmValue[]) = > WasmValue;
// type WasmExport = {name : string} & ({func : number} | {table : number} |
//                                      {mem : number} | {global : number});
// type WasmImport = {name : string, module : string} &
//                   ({func : number} | {table : number} | {mem : number} |
//                    {global : number});
// interface WasmInterface {
//   $globalX: WasmValue;
//   $varX: WasmValue;
//   $funcX(a : WasmValue /*, ...*/) : WasmValue;
//   readonly $memoryX : WebAssembly.Memory;
//   readonly $tableX : WebAssembly.Table;
//   readonly memories : {[nameOrIndex:string | number] : WebAssembly.Memory};
//   readonly tables : {[nameOrIndex:string | number] : WebAssembly.Table};
//   readonly stack : WasmValue[];
//   readonly imports : {[nameOrIndex:string | number] : WasmImport};
//   readonly exports : {[nameOrIndex:string | number] : WasmExport};
//   readonly globals : {[nameOrIndex:string | number] : WasmValue};
//   readonly locals : {[nameOrIndex:string | number] : WasmValue};
//   readonly functions : {[nameOrIndex:string | number] : WasmFunction};
// }
//
// The wasm index spaces memories, tables, imports, exports, globals, locals
// functions are JSProxies that lazily produce values either by index or by
// name. A top level JSProxy is wrapped around those for top-level lookup of
// names in the disambiguation order  memory, local, table, function, global.
// Import and export names are not globally resolved.

Handle<JSProxy> WasmJs::GetJSDebugProxy(WasmFrame* frame) {
  Isolate* isolate = frame->isolate();
  Factory* factory = isolate->factory();
  Handle<WasmInstanceObject> instance(frame->wasm_instance(), isolate);

  // The top level proxy delegates lookups to the index space proxies.
  Handle<JSObject> handler = factory->NewJSObjectWithNullProto();
  InstallFunc(isolate, handler, "get", ToplevelGetTrapCallback, 3, false,
              READ_ONLY);
  InstallFunc(isolate, handler, "has", ToplevelHasTrapCallback, 2, false,
              READ_ONLY);

  Handle<JSObject> target = factory->NewJSObjectWithNullProto();

  // Generate JSMaps per index space for name->index lookup. Every index space
  // proxy is associated with its table for local name lookup.

  auto local_name_table =
      GetNameTable(isolate, GetLocalNames(instance, frame->pc()));
  auto locals =
      GetJSProxy(frame, local_name_table, GetTrapCallback<GetLocalImpl>,
                 HasTrapCallback<HasLocalImpl>);
  JSObject::AddProperty(isolate, target, "locals", locals, READ_ONLY);

  auto global_name_table = GetNameTable(isolate, GetGlobalNames(instance));
  auto globals =
      GetJSProxy(frame, global_name_table, GetTrapCallback<GetGlobalImpl>,
                 HasTrapCallback<HasGlobalImpl>);
  JSObject::AddProperty(isolate, target, "globals", globals, READ_ONLY);

  auto function_name_table = GetNameTable(isolate, GetFunctionNames(instance));
  auto functions =
      GetJSProxy(frame, function_name_table, GetTrapCallback<GetFunctionImpl>,
                 HasTrapCallback<HasFunctionImpl>);
  JSObject::AddProperty(isolate, target, "functions", functions, READ_ONLY);

  auto memory_name_table = GetNameTable(isolate, GetMemoryNames(instance));
  auto memories =
      GetJSProxy(frame, memory_name_table, GetTrapCallback<GetMemoryImpl>,
                 HasTrapCallback<HasMemoryImpl>);
  JSObject::AddProperty(isolate, target, "memories", memories, READ_ONLY);

  auto table_name_table = GetNameTable(isolate, GetTableNames(instance));
  auto tables =
      GetJSProxy(frame, table_name_table, GetTrapCallback<GetTableImpl>,
                 HasTrapCallback<HasTableImpl>);
  JSObject::AddProperty(isolate, target, "tables", tables, READ_ONLY);

  auto import_name_table = GetNameTable(isolate, GetImportNames(instance));
  auto imports =
      GetJSProxy(frame, import_name_table, GetTrapCallback<GetImportImpl>,
                 HasTrapCallback<HasImportImpl>);
  JSObject::AddProperty(isolate, target, "imports", imports, READ_ONLY);

  auto export_name_table = GetNameTable(isolate, GetExportNames(instance));
  auto exports =
      GetJSProxy(frame, export_name_table, GetTrapCallback<GetExportImpl>,
                 HasTrapCallback<HasExportImpl>);
  JSObject::AddProperty(isolate, target, "exports", exports, READ_ONLY);

  auto stack = GetStackObject(frame);
  JSObject::AddProperty(isolate, target, "stack", stack, READ_ONLY);

  return factory->NewJSProxy(target, handler);
}

#undef ASSIGN
#undef EXTRACT_THIS

}  // namespace internal
}  // namespace v8
