// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.

#include "node_contextify.h"

#include "base_object-inl.h"
#include "cppgc/allocation.h"
#include "memory_tracker-inl.h"
#include "module_wrap.h"
#include "node_context_data.h"
#include "node_errors.h"
#include "node_external_reference.h"
#include "node_internals.h"
#include "node_process.h"
#include "node_sea.h"
#include "node_snapshot_builder.h"
#include "node_url.h"
#include "node_watchdog.h"
#include "util-inl.h"

namespace node {
namespace contextify {

using errors::TryCatchScope;

using v8::Array;
using v8::ArrayBufferView;
using v8::Boolean;
using v8::Context;
using v8::DictionaryTemplate;
using v8::EscapableHandleScope;
using v8::Function;
using v8::FunctionCallbackInfo;
using v8::FunctionTemplate;
using v8::HandleScope;
using v8::IndexedPropertyHandlerConfiguration;
using v8::IndexFilter;
using v8::Int32;
using v8::Integer;
using v8::Intercepted;
using v8::Isolate;
using v8::JustVoid;
using v8::KeyCollectionMode;
using v8::Local;
using v8::LocalVector;
using v8::Maybe;
using v8::MaybeLocal;
using v8::MeasureMemoryExecution;
using v8::MeasureMemoryMode;
using v8::Message;
using v8::MicrotaskQueue;
using v8::MicrotasksPolicy;
using v8::Name;
using v8::NamedPropertyHandlerConfiguration;
using v8::Nothing;
using v8::Object;
using v8::ObjectTemplate;
using v8::PrimitiveArray;
using v8::Promise;
using v8::PropertyAttribute;
using v8::PropertyCallbackInfo;
using v8::PropertyDescriptor;
using v8::PropertyFilter;
using v8::PropertyHandlerFlags;
using v8::Script;
using v8::ScriptCompiler;
using v8::ScriptOrigin;
using v8::String;
using v8::Symbol;
using v8::Uint32;
using v8::UnboundScript;
using v8::Value;

// The vm module executes code in a sandboxed environment with a different
// global object than the rest of the code. This is achieved by applying
// every call that changes or queries a property on the global `this` in the
// sandboxed code, to the sandbox object.
//
// The implementation uses V8's interceptors for methods like `set`, `get`,
// `delete`, `defineProperty`, and for any query of the property attributes.
// Property handlers with interceptors are set on the object template for
// the sandboxed code. Handlers for both named properties and for indexed
// properties are used. Their functionality is almost identical, the indexed
// interceptors mostly just call the named interceptors.
//
// For every `get` of a global property in the sandboxed context, the
// interceptor callback checks the sandbox object for the property.
// If the property is defined on the sandbox, that result is returned to
// the original call instead of finishing the query on the global object.
//
// For every `set` of a global property, the interceptor callback defines or
// changes the property both on the sandbox and the global proxy.

namespace {

// Convert an int to a V8 Name (String or Symbol).
MaybeLocal<String> Uint32ToName(Local<Context> context, uint32_t index) {
  return Uint32::New(Isolate::GetCurrent(), index)->ToString(context);
}

}  // anonymous namespace

ContextifyContext* ContextifyContext::New(Environment* env,
                                          Local<Object> sandbox_obj,
                                          ContextOptions* options) {
  Local<ObjectTemplate> object_template;
  HandleScope scope(env->isolate());
  CHECK_IMPLIES(sandbox_obj.IsEmpty(), options->vanilla);
  if (!sandbox_obj.IsEmpty()) {
    // Do not use the template with interceptors for vanilla contexts.
    object_template = env->contextify_global_template();
    DCHECK(!object_template.IsEmpty());
  }

  const SnapshotData* snapshot_data = env->isolate_data()->snapshot_data();

  MicrotaskQueue* queue =
      options->own_microtask_queue
          ? options->own_microtask_queue.get()
          : env->isolate()->GetCurrentContext()->GetMicrotaskQueue();

  Local<Context> v8_context;
  if (!(CreateV8Context(env->isolate(), object_template, snapshot_data, queue)
            .ToLocal(&v8_context))) {
    // Allocation failure, maximum call stack size reached, termination, etc.
    return {};
  }
  return New(v8_context, env, sandbox_obj, options);
}

void ContextifyContext::Trace(cppgc::Visitor* visitor) const {
  CppgcMixin::Trace(visitor);
  visitor->Trace(context_);
}

ContextifyContext::ContextifyContext(Environment* env,
                                     Local<Object> wrapper,
                                     Local<Context> v8_context,
                                     ContextOptions* options)
    : microtask_queue_(options->own_microtask_queue
                           ? options->own_microtask_queue.release()
                           : nullptr) {
  CppgcMixin::Wrap(this, env, wrapper);

  context_.Reset(env->isolate(), v8_context);
  // This should only be done after the initial initializations of the context
  // global object is finished.
  DCHECK_NULL(v8_context->GetAlignedPointerFromEmbedderData(
      ContextEmbedderIndex::kContextifyContext,
      EmbedderDataTag::kPerContextData));
  v8_context->SetAlignedPointerInEmbedderData(
      ContextEmbedderIndex::kContextifyContext,
      this,
      EmbedderDataTag::kPerContextData);
}

void ContextifyContext::InitializeGlobalTemplates(IsolateData* isolate_data) {
  DCHECK(isolate_data->contextify_wrapper_template().IsEmpty());
  Local<FunctionTemplate> global_func_template =
      FunctionTemplate::New(isolate_data->isolate());
  Local<ObjectTemplate> global_object_template =
      global_func_template->InstanceTemplate();

  NamedPropertyHandlerConfiguration config(
      PropertyGetterCallback,
      PropertySetterCallback,
      PropertyQueryCallback,
      PropertyDeleterCallback,
      PropertyEnumeratorCallback,
      PropertyDefinerCallback,
      PropertyDescriptorCallback,
      {},
      PropertyHandlerFlags::kHasNoSideEffect);

  IndexedPropertyHandlerConfiguration indexed_config(
      IndexedPropertyGetterCallback,
      IndexedPropertySetterCallback,
      IndexedPropertyQueryCallback,
      IndexedPropertyDeleterCallback,
      IndexedPropertyEnumeratorCallback,
      IndexedPropertyDefinerCallback,
      IndexedPropertyDescriptorCallback,
      {},
      PropertyHandlerFlags::kHasNoSideEffect);

  global_object_template->SetHandler(config);
  global_object_template->SetHandler(indexed_config);
  isolate_data->set_contextify_global_template(global_object_template);

  Local<FunctionTemplate> wrapper_func_template =
      BaseObject::MakeLazilyInitializedJSTemplate(isolate_data);
  Local<ObjectTemplate> wrapper_object_template =
      wrapper_func_template->InstanceTemplate();
  isolate_data->set_contextify_wrapper_template(wrapper_object_template);
}

MaybeLocal<Context> ContextifyContext::CreateV8Context(
    Isolate* isolate,
    Local<ObjectTemplate> object_template,
    const SnapshotData* snapshot_data,
    MicrotaskQueue* queue) {
  EscapableHandleScope scope(isolate);

  Local<Context> ctx;
  if (object_template.IsEmpty() || snapshot_data == nullptr) {
    ctx = Context::New(
        isolate,
        nullptr,  // extensions
        object_template,
        {},                                       // global object
        v8::DeserializeInternalFieldsCallback(),  // deserialization callback
        queue);
    if (ctx.IsEmpty() || InitializeBaseContextForSnapshot(ctx).IsNothing()) {
      return MaybeLocal<Context>();
    }
  } else if (!Context::FromSnapshot(
                  isolate,
                  SnapshotData::kNodeVMContextIndex,
                  v8::DeserializeInternalFieldsCallback(),  // deserialization
                                                            // callback
                  nullptr,                                  // extensions
                  {},                                       // global object
                  queue)
                  .ToLocal(&ctx)) {
    return MaybeLocal<Context>();
  }

  return scope.Escape(ctx);
}

ContextifyContext* ContextifyContext::New(Local<Context> v8_context,
                                          Environment* env,
                                          Local<Object> sandbox_obj,
                                          ContextOptions* options) {
  HandleScope scope(env->isolate());
  CHECK_IMPLIES(sandbox_obj.IsEmpty(), options->vanilla);
  // This only initializes part of the context. The primordials are
  // only initialized when needed because even deserializing them slows
  // things down significantly and they are only needed in rare occasions
  // in the vm contexts.
  if (InitializeContextRuntime(v8_context).IsNothing()) {
    return {};
  }

  Local<Context> main_context = env->context();
  Local<Object> new_context_global = v8_context->Global();
  v8_context->SetSecurityToken(main_context->GetSecurityToken());

  // We need to tie the lifetime of the sandbox object with the lifetime of
  // newly created context. We do this by making them hold references to each
  // other. The context can directly hold a reference to the sandbox as an
  // embedder data field. The sandbox uses a private symbol to hold a reference
  // to the ContextifyContext wrapper which in turn internally references
  // the context from its constructor.
  if (sandbox_obj.IsEmpty()) {
    v8_context->SetEmbedderData(ContextEmbedderIndex::kSandboxObject,
                                v8::Undefined(env->isolate()));
  } else {
    v8_context->SetEmbedderData(ContextEmbedderIndex::kSandboxObject,
                                sandbox_obj);
  }

  // Delegate the code generation validation to
  // node::ModifyCodeGenerationFromStrings.
  v8_context->AllowCodeGenerationFromStrings(false);
  v8_context->SetEmbedderData(
      ContextEmbedderIndex::kAllowCodeGenerationFromStrings,
      options->allow_code_gen_strings);
  v8_context->SetEmbedderData(ContextEmbedderIndex::kAllowWasmCodeGeneration,
                              options->allow_code_gen_wasm);

  Utf8Value name_val(env->isolate(), options->name);
  ContextInfo info(name_val.ToString());
  if (!options->origin.IsEmpty()) {
    Utf8Value origin_val(env->isolate(), options->origin);
    info.origin = origin_val.ToString();
  }

  ContextifyContext* result;
  Local<Object> wrapper;
  {
    Context::Scope context_scope(v8_context);
    if (!sandbox_obj.IsEmpty()) {
      Local<String> ctor_name = sandbox_obj->GetConstructorName();
      if (!ctor_name->Equals(v8_context, env->object_string())
               .FromMaybe(false) &&
          new_context_global
              ->DefineOwnProperty(
                  v8_context,
                  v8::Symbol::GetToStringTag(env->isolate()),
                  ctor_name,
                  static_cast<v8::PropertyAttribute>(v8::DontEnum))
              .IsNothing()) {
        return {};
      }
    }

    // Assign host_defined_options_id to the global object so that in the
    // callback of ImportModuleDynamically, we can get the
    // host_defined_options_id from the v8::Context without accessing the
    // wrapper object.
    if (new_context_global
            ->SetPrivate(v8_context,
                         env->host_defined_option_symbol(),
                         options->host_defined_options_id)
            .IsNothing()) {
      return {};
    }

    env->AssignToContext(v8_context, nullptr, info);

    if (!env->contextify_wrapper_template()
             ->NewInstance(v8_context)
             .ToLocal(&wrapper)) {
      return {};
    }
    DCHECK_NOT_NULL(env->isolate()->GetCppHeap());
    result = cppgc::MakeGarbageCollected<ContextifyContext>(
        env->cppgc_allocation_handle(), env, wrapper, v8_context, options);
  }

  Local<Object> wrapper_holder =
      sandbox_obj.IsEmpty() ? new_context_global : sandbox_obj;
  if (!wrapper_holder.IsEmpty() &&
      wrapper_holder
          ->SetPrivate(
              v8_context, env->contextify_context_private_symbol(), wrapper)
          .IsNothing()) {
    return {};
  }

  // Assign host_defined_options_id to the sandbox object or the global object
  // (for vanilla contexts) so that module callbacks like
  // importModuleDynamically can be registered once back to the JS land.
  if (!sandbox_obj.IsEmpty() &&
      sandbox_obj
          ->SetPrivate(v8_context,
                       env->host_defined_option_symbol(),
                       options->host_defined_options_id)
          .IsNothing()) {
    return {};
  }
  return result;
}

void ContextifyContext::CreatePerIsolateProperties(
    IsolateData* isolate_data, Local<ObjectTemplate> target) {
  Isolate* isolate = isolate_data->isolate();
  SetMethod(isolate, target, "makeContext", MakeContext);
}

void ContextifyContext::RegisterExternalReferences(
    ExternalReferenceRegistry* registry) {
  registry->Register(MakeContext);
  registry->Register(PropertyQueryCallback);
  registry->Register(PropertyGetterCallback);
  registry->Register(PropertySetterCallback);
  registry->Register(PropertyDescriptorCallback);
  registry->Register(PropertyDeleterCallback);
  registry->Register(PropertyEnumeratorCallback);
  registry->Register(PropertyDefinerCallback);
  registry->Register(IndexedPropertyQueryCallback);
  registry->Register(IndexedPropertyGetterCallback);
  registry->Register(IndexedPropertySetterCallback);
  registry->Register(IndexedPropertyDescriptorCallback);
  registry->Register(IndexedPropertyDeleterCallback);
  registry->Register(IndexedPropertyDefinerCallback);
  registry->Register(IndexedPropertyEnumeratorCallback);
}

// makeContext(sandbox, name, origin, strings, wasm);
void ContextifyContext::MakeContext(const FunctionCallbackInfo<Value>& args) {
  Environment* env = Environment::GetCurrent(args);
  ContextOptions options;

  CHECK_EQ(args.Length(), 7);
  Local<Object> sandbox;
  if (args[0]->IsObject()) {
    sandbox = args[0].As<Object>();
    // Don't allow contextifying a sandbox multiple times.
    CHECK(!sandbox
               ->HasPrivate(env->context(),
                            env->contextify_context_private_symbol())
               .FromJust());
  } else {
    CHECK(args[0]->IsSymbol());
    options.vanilla = true;
  }

  CHECK(args[1]->IsString());
  options.name = args[1].As<String>();

  CHECK(args[2]->IsString() || args[2]->IsUndefined());
  if (args[2]->IsString()) {
    options.origin = args[2].As<String>();
  }

  CHECK(args[3]->IsBoolean());
  options.allow_code_gen_strings = args[3].As<Boolean>();

  CHECK(args[4]->IsBoolean());
  options.allow_code_gen_wasm = args[4].As<Boolean>();

  if (args[5]->IsBoolean() && args[5]->BooleanValue(env->isolate())) {
    options.own_microtask_queue =
        MicrotaskQueue::New(env->isolate(), MicrotasksPolicy::kExplicit);
  }

  CHECK(args[6]->IsSymbol());
  options.host_defined_options_id = args[6].As<Symbol>();

  TryCatchScope try_catch(env);
  ContextifyContext* context_ptr =
      ContextifyContext::New(env, sandbox, &options);

  if (try_catch.HasCaught()) {
    if (!try_catch.HasTerminated())
      try_catch.ReThrow();
    return;
  }

  if (sandbox.IsEmpty()) {
    args.GetReturnValue().Set(context_ptr->context()->Global());
  } else {
    args.GetReturnValue().Set(sandbox);
  }
}

// static
ContextifyContext* ContextifyContext::ContextFromContextifiedSandbox(
    Environment* env, const Local<Object>& wrapper_holder) {
  Local<Value> contextify;
  if (wrapper_holder
          ->GetPrivate(env->context(), env->contextify_context_private_symbol())
          .ToLocal(&contextify) &&
      contextify->IsObject()) {
    return Unwrap<ContextifyContext>(contextify.As<Object>());
  }
  return nullptr;
}

template <typename T>
ContextifyContext* ContextifyContext::Get(const PropertyCallbackInfo<T>& args) {
  // TODO(joyeecheung): it should be fine to simply use
  // args.GetIsolate()->GetCurrentContext() and take the pointer at
  // ContextEmbedderIndex::kContextifyContext, as V8 is supposed to
  // push the creation context before invoking these callbacks.
  return Get(args.HolderV2());
}

ContextifyContext* ContextifyContext::Get(Local<Object> object) {
  Local<Context> context;
  if (!object->GetCreationContext().ToLocal(&context)) {
    return nullptr;
  }
  if (!ContextEmbedderTag::IsNodeContext(context)) {
    return nullptr;
  }
  return static_cast<ContextifyContext*>(
      context->GetAlignedPointerFromEmbedderData(
          ContextEmbedderIndex::kContextifyContext,
          EmbedderDataTag::kPerContextData));
}

bool ContextifyContext::IsStillInitializing(const ContextifyContext* ctx) {
  return ctx == nullptr || ctx->context_.IsEmpty();
}

// static
Intercepted ContextifyContext::PropertyQueryCallback(
    Local<Name> property, const PropertyCallbackInfo<Integer>& args) {
  ContextifyContext* ctx = ContextifyContext::Get(args);

  // Still initializing
  if (IsStillInitializing(ctx)) {
    return Intercepted::kNo;
  }

  Local<Context> context = ctx->context();
  Local<Object> sandbox = ctx->sandbox();

  PropertyAttribute attr;

  Maybe<bool> maybe_has = sandbox->HasRealNamedProperty(context, property);
  if (maybe_has.IsNothing()) {
    return Intercepted::kNo;
  } else if (maybe_has.FromJust()) {
    Maybe<PropertyAttribute> maybe_attr =
        sandbox->GetRealNamedPropertyAttributes(context, property);
    if (!maybe_attr.To(&attr)) {
      return Intercepted::kNo;
    }
    args.GetReturnValue().Set(attr);
    return Intercepted::kYes;
  } else {
    maybe_has = ctx->global_proxy()->HasRealNamedProperty(context, property);
    if (maybe_has.IsNothing()) {
      return Intercepted::kNo;
    } else if (maybe_has.FromJust()) {
      Maybe<PropertyAttribute> maybe_attr =
          ctx->global_proxy()->GetRealNamedPropertyAttributes(context,
                                                              property);
      if (!maybe_attr.To(&attr)) {
        return Intercepted::kNo;
      }
      args.GetReturnValue().Set(attr);
      return Intercepted::kYes;
    }
  }

  return Intercepted::kNo;
}

// static
Intercepted ContextifyContext::PropertyGetterCallback(
    Local<Name> property, const PropertyCallbackInfo<Value>& args) {
  Environment* env = Environment::GetCurrent(args);
  ContextifyContext* ctx = ContextifyContext::Get(args);

  // Still initializing
  if (IsStillInitializing(ctx)) {
    return Intercepted::kNo;
  }

  Local<Context> context = ctx->context();
  Local<Object> sandbox = ctx->sandbox();

  TryCatchScope try_catch(env);
  MaybeLocal<Value> maybe_rv =
      sandbox->GetRealNamedProperty(context, property);
  if (maybe_rv.IsEmpty()) {
    maybe_rv =
        ctx->global_proxy()->GetRealNamedProperty(context, property);
  }

  Local<Value> rv;
  if (maybe_rv.ToLocal(&rv)) {
    if (try_catch.HasCaught() && !try_catch.HasTerminated()) {
      try_catch.ReThrow();
    }
    if (rv == sandbox)
      rv = ctx->global_proxy();

    args.GetReturnValue().Set(rv);
    return Intercepted::kYes;
  }
  return Intercepted::kNo;
}

// static
Intercepted ContextifyContext::PropertySetterCallback(
    Local<Name> property,
    Local<Value> value,
    const PropertyCallbackInfo<void>& args) {
  ContextifyContext* ctx = ContextifyContext::Get(args);

  // Still initializing
  if (IsStillInitializing(ctx)) {
    return Intercepted::kNo;
  }

  Local<Context> context = ctx->context();
  PropertyAttribute attributes = PropertyAttribute::None;
  bool is_declared_on_global_proxy = ctx->global_proxy()
      ->GetRealNamedPropertyAttributes(context, property)
      .To(&attributes);
  bool read_only =
      static_cast<int>(attributes) &
      static_cast<int>(PropertyAttribute::ReadOnly);

  bool is_declared_on_sandbox = ctx->sandbox()
      ->GetRealNamedPropertyAttributes(context, property)
      .To(&attributes);
  read_only = read_only ||
      (static_cast<int>(attributes) &
      static_cast<int>(PropertyAttribute::ReadOnly));

  if (read_only) {
    return Intercepted::kNo;
  }

  // V8 comment: As long as the context is not detached the contextual accesses
  // are the same as regular accesses to `context->Global()`s data property.
  // The only difference is that after detaching `args.Holder()` will
  // become a new identity and will no longer be equal to `context->Global()`.
  // TODO(Node.js): revise the code below as the "contextual"-ness of the
  // store is not actually relevant here. Also, new variable declaration is
  // reported by V8 via PropertyDefinerCallback.
  bool is_declared = is_declared_on_global_proxy || is_declared_on_sandbox;

/*
  // true for x = 5
  // false for this.x = 5
  // false for Object.defineProperty(this, 'foo', ...)
  // false for vmResult.x = 5 where vmResult = vm.runInContext();

  bool is_contextual_store = ctx->global_proxy() != args.This();

  // Indicator to not return before setting (undeclared) function declarations
  // on the sandbox in strict mode, i.e. args.ShouldThrowOnError() = true.
  // True for 'function f() {}', 'this.f = function() {}',
  // 'var f = function()'.
  // In effect only for 'function f() {}' because
  // var f = function(), is_declared = true
  // this.f = function() {}, is_contextual_store = false.
  bool is_function = value->IsFunction();

  bool is_declared = is_declared_on_global_proxy || is_declared_on_sandbox;
  if (!is_declared && args.ShouldThrowOnError() && is_contextual_store &&
      !is_function) {
    return Intercepted::kNo;
  }
*/
  if (!is_declared && property->IsSymbol()) {
    return Intercepted::kNo;
  }
  if (ctx->sandbox()->Set(context, property, value).IsNothing()) {
    return Intercepted::kNo;
  }

  Local<Value> desc;
  if (is_declared_on_sandbox &&
      ctx->sandbox()
          ->GetOwnPropertyDescriptor(context, property)
          .ToLocal(&desc) &&
      !desc->IsUndefined()) {
    Environment* env = Environment::GetCurrent(context);
    Local<Object> desc_obj = desc.As<Object>();

    // We have to specify the return value for any contextual or get/set
    // property
    if (desc_obj->HasOwnProperty(context, env->get_string()).FromMaybe(false) ||
        desc_obj->HasOwnProperty(context, env->set_string()).FromMaybe(false)) {
      return Intercepted::kYes;
    }
  }
  return Intercepted::kNo;
}

// static
Intercepted ContextifyContext::PropertyDescriptorCallback(
    Local<Name> property, const PropertyCallbackInfo<Value>& args) {
  ContextifyContext* ctx = ContextifyContext::Get(args);

  // Still initializing
  if (IsStillInitializing(ctx)) {
    return Intercepted::kNo;
  }

  Local<Context> context = ctx->context();

  Local<Object> sandbox = ctx->sandbox();

  if (sandbox->HasOwnProperty(context, property).FromMaybe(false)) {
    Local<Value> desc;
    if (sandbox->GetOwnPropertyDescriptor(context, property).ToLocal(&desc)) {
      args.GetReturnValue().Set(desc);
      return Intercepted::kYes;
    }
  }
  return Intercepted::kNo;
}

// static
Intercepted ContextifyContext::PropertyDefinerCallback(
    Local<Name> property,
    const PropertyDescriptor& desc,
    const PropertyCallbackInfo<void>& args) {
  ContextifyContext* ctx = ContextifyContext::Get(args);

  // Still initializing
  if (IsStillInitializing(ctx)) {
    return Intercepted::kNo;
  }

  Local<Context> context = ctx->context();
  Isolate* isolate = Isolate::GetCurrent();

  PropertyAttribute attributes = PropertyAttribute::None;
  bool is_declared =
      ctx->global_proxy()->GetRealNamedPropertyAttributes(context,
                                                          property)
          .To(&attributes);
  bool read_only =
      static_cast<int>(attributes) &
          static_cast<int>(PropertyAttribute::ReadOnly);
  bool dont_delete = static_cast<int>(attributes) &
                     static_cast<int>(PropertyAttribute::DontDelete);

  // If the property is set on the global as neither writable nor
  // configurable, don't change it on the global or sandbox.
  if (is_declared && read_only && dont_delete) {
    return Intercepted::kNo;
  }

  Local<Object> sandbox = ctx->sandbox();

  auto define_prop_on_sandbox =
      [&] (PropertyDescriptor* desc_for_sandbox) {
        if (desc.has_enumerable()) {
          desc_for_sandbox->set_enumerable(desc.enumerable());
        }
        if (desc.has_configurable()) {
          desc_for_sandbox->set_configurable(desc.configurable());
        }
        // Set the property on the sandbox.
        USE(sandbox->DefineProperty(context, property, *desc_for_sandbox));
      };

  if (desc.has_get() || desc.has_set()) {
    PropertyDescriptor desc_for_sandbox(
        desc.has_get() ? desc.get() : Undefined(isolate).As<Value>(),
        desc.has_set() ? desc.set() : Undefined(isolate).As<Value>());

    define_prop_on_sandbox(&desc_for_sandbox);
    // TODO(https://github.com/nodejs/node/issues/52634): this should return
    // kYes to behave according to the expected semantics.
    return Intercepted::kNo;
  } else {
    Local<Value> value =
        desc.has_value() ? desc.value() : Undefined(isolate).As<Value>();

    if (desc.has_writable()) {
      PropertyDescriptor desc_for_sandbox(value, desc.writable());
      define_prop_on_sandbox(&desc_for_sandbox);
    } else {
      PropertyDescriptor desc_for_sandbox(value);
      define_prop_on_sandbox(&desc_for_sandbox);
    }
    // TODO(https://github.com/nodejs/node/issues/52634): this should return
    // kYes to behave according to the expected semantics.
    return Intercepted::kNo;
  }
}

// static
Intercepted ContextifyContext::PropertyDeleterCallback(
    Local<Name> property, const PropertyCallbackInfo<Boolean>& args) {
  ContextifyContext* ctx = ContextifyContext::Get(args);

  // Still initializing
  if (IsStillInitializing(ctx)) {
    return Intercepted::kNo;
  }

  Maybe<bool> success = ctx->sandbox()->Delete(ctx->context(), property);

  if (success.FromMaybe(false)) {
    return Intercepted::kNo;
  }

  // Delete failed on the sandbox, intercept and do not delete on
  // the global object.
  args.GetReturnValue().Set(false);
  return Intercepted::kYes;
}

// static
void ContextifyContext::PropertyEnumeratorCallback(
    const PropertyCallbackInfo<Array>& args) {
  // Named enumerator will be invoked on Object.keys,
  // Object.getOwnPropertyNames, Object.getOwnPropertySymbols,
  // Object.getOwnPropertyDescriptors, for...in, etc. operations.
  // Named enumerator should return all own non-indices property names,
  // including string properties and symbol properties. V8 will filter the
  // result array to match the expected symbol-only, enumerable-only with
  // NamedPropertyQueryCallback.
  ContextifyContext* ctx = ContextifyContext::Get(args);

  // Still initializing
  if (IsStillInitializing(ctx)) return;

  Local<Array> properties;
  // Only get own named properties, exclude indices.
  if (!ctx->sandbox()
           ->GetPropertyNames(
               ctx->context(),
               KeyCollectionMode::kOwnOnly,
               static_cast<PropertyFilter>(PropertyFilter::ALL_PROPERTIES),
               IndexFilter::kSkipIndices)
           .ToLocal(&properties))
    return;

  args.GetReturnValue().Set(properties);
}

// static
void ContextifyContext::IndexedPropertyEnumeratorCallback(
    const PropertyCallbackInfo<Array>& args) {
  // Indexed enumerator will be invoked on Object.keys,
  // Object.getOwnPropertyNames, Object.getOwnPropertyDescriptors, for...in,
  // etc. operations. Indexed enumerator should return all own non-indices index
  // properties. V8 will filter the result array to match the expected
  // enumerable-only with IndexedPropertyQueryCallback.

  Isolate* isolate = args.GetIsolate();
  HandleScope scope(isolate);
  ContextifyContext* ctx = ContextifyContext::Get(args);
  Local<Context> context = ctx->context();

  // Still initializing
  if (IsStillInitializing(ctx)) return;

  Local<Array> properties;

  // Only get own index properties.
  if (!ctx->sandbox()
           ->GetPropertyNames(
               context,
               KeyCollectionMode::kOwnOnly,
               static_cast<PropertyFilter>(PropertyFilter::SKIP_SYMBOLS),
               IndexFilter::kIncludeIndices)
           .ToLocal(&properties))
    return;

  std::vector<v8::Global<Value>> properties_vec;
  if (FromV8Array(context, properties, &properties_vec).IsNothing()) {
    return;
  }

  // Filter out non-number property names.
  LocalVector<Value> indices(isolate);
  for (uint32_t i = 0; i < properties->Length(); i++) {
    Local<Value> prop = properties_vec[i].Get(isolate);
    if (!prop->IsNumber()) {
      continue;
    }
    indices.push_back(prop);
  }

  args.GetReturnValue().Set(
      Array::New(args.GetIsolate(), indices.data(), indices.size()));
}

// static
Intercepted ContextifyContext::IndexedPropertyQueryCallback(
    uint32_t index, const PropertyCallbackInfo<Integer>& args) {
  ContextifyContext* ctx = ContextifyContext::Get(args);

  // Still initializing
  if (IsStillInitializing(ctx)) {
    return Intercepted::kNo;
  }

  Local<String> name;
  if (Uint32ToName(ctx->context(), index).ToLocal(&name)) {
    return ContextifyContext::PropertyQueryCallback(name, args);
  }
  return Intercepted::kNo;
}

// static
Intercepted ContextifyContext::IndexedPropertyGetterCallback(
    uint32_t index, const PropertyCallbackInfo<Value>& args) {
  ContextifyContext* ctx = ContextifyContext::Get(args);

  // Still initializing
  if (IsStillInitializing(ctx)) {
    return Intercepted::kNo;
  }

  Local<String> name;
  if (Uint32ToName(ctx->context(), index).ToLocal(&name)) {
    return ContextifyContext::PropertyGetterCallback(name, args);
  }
  return Intercepted::kNo;
}

Intercepted ContextifyContext::IndexedPropertySetterCallback(
    uint32_t index,
    Local<Value> value,
    const PropertyCallbackInfo<void>& args) {
  ContextifyContext* ctx = ContextifyContext::Get(args);

  // Still initializing
  if (IsStillInitializing(ctx)) {
    return Intercepted::kNo;
  }

  Local<String> name;
  if (Uint32ToName(ctx->context(), index).ToLocal(&name)) {
    return ContextifyContext::PropertySetterCallback(name, value, args);
  }
  return Intercepted::kNo;
}

// static
Intercepted ContextifyContext::IndexedPropertyDescriptorCallback(
    uint32_t index, const PropertyCallbackInfo<Value>& args) {
  ContextifyContext* ctx = ContextifyContext::Get(args);

  // Still initializing
  if (IsStillInitializing(ctx)) {
    return Intercepted::kNo;
  }

  Local<String> name;
  if (Uint32ToName(ctx->context(), index).ToLocal(&name)) {
    return ContextifyContext::PropertyDescriptorCallback(name, args);
  }
  return Intercepted::kNo;
}

Intercepted ContextifyContext::IndexedPropertyDefinerCallback(
    uint32_t index,
    const PropertyDescriptor& desc,
    const PropertyCallbackInfo<void>& args) {
  ContextifyContext* ctx = ContextifyContext::Get(args);

  // Still initializing
  if (IsStillInitializing(ctx)) {
    return Intercepted::kNo;
  }

  Local<String> name;
  if (Uint32ToName(ctx->context(), index).ToLocal(&name)) {
    return ContextifyContext::PropertyDefinerCallback(name, desc, args);
  }
  return Intercepted::kNo;
}

// static
Intercepted ContextifyContext::IndexedPropertyDeleterCallback(
    uint32_t index, const PropertyCallbackInfo<Boolean>& args) {
  ContextifyContext* ctx = ContextifyContext::Get(args);

  // Still initializing
  if (IsStillInitializing(ctx)) {
    return Intercepted::kNo;
  }

  Maybe<bool> success = ctx->sandbox()->Delete(ctx->context(), index);

  if (success.FromMaybe(false)) {
    return Intercepted::kNo;
  }

  // Delete failed on the sandbox, intercept and do not delete on
  // the global object.
  args.GetReturnValue().Set(false);
  return Intercepted::kYes;
}

void ContextifyScript::CreatePerIsolateProperties(
    IsolateData* isolate_data, Local<ObjectTemplate> target) {
  Isolate* isolate = isolate_data->isolate();
  Local<String> class_name = FIXED_ONE_BYTE_STRING(isolate, "ContextifyScript");

  Local<FunctionTemplate> script_tmpl = NewFunctionTemplate(isolate, New);
  script_tmpl->InstanceTemplate()->SetInternalFieldCount(
      ContextifyScript::kInternalFieldCount);
  script_tmpl->SetClassName(class_name);
  SetProtoMethod(isolate, script_tmpl, "createCachedData", CreateCachedData);
  SetProtoMethod(isolate, script_tmpl, "runInContext", RunInContext);

  target->Set(isolate, "ContextifyScript", script_tmpl);
  isolate_data->set_script_context_constructor_template(script_tmpl);
}

void ContextifyScript::RegisterExternalReferences(
    ExternalReferenceRegistry* registry) {
  registry->Register(New);
  registry->Register(CreateCachedData);
  registry->Register(RunInContext);
}

ContextifyScript* ContextifyScript::New(Environment* env,
                                        Local<Object> object) {
  DCHECK_NOT_NULL(env->isolate()->GetCppHeap());
  return cppgc::MakeGarbageCollected<ContextifyScript>(
      env->cppgc_allocation_handle(), env, object);
}

void ContextifyScript::New(const FunctionCallbackInfo<Value>& args) {
  Environment* env = Environment::GetCurrent(args);
  Isolate* isolate = env->isolate();
  Local<Context> context = env->context();

  CHECK(args.IsConstructCall());

  const int argc = args.Length();
  CHECK_GE(argc, 2);

  CHECK(args[0]->IsString());
  Local<String> code = args[0].As<String>();

  CHECK(args[1]->IsString());
  Local<String> filename = args[1].As<String>();

  int line_offset = 0;
  int column_offset = 0;
  Local<ArrayBufferView> cached_data_buf;
  bool produce_cached_data = false;
  Local<Context> parsing_context = context;

  Local<Symbol> id_symbol;
  if (argc > 2) {
    // new ContextifyScript(code, filename, lineOffset, columnOffset,
    //                      cachedData, produceCachedData, parsingContext,
    //                      hostDefinedOptionId)
    CHECK_EQ(argc, 8);
    CHECK(args[2]->IsNumber());
    line_offset = args[2].As<Int32>()->Value();
    CHECK(args[3]->IsNumber());
    column_offset = args[3].As<Int32>()->Value();
    if (!args[4]->IsUndefined()) {
      CHECK(args[4]->IsArrayBufferView());
      cached_data_buf = args[4].As<ArrayBufferView>();
    }
    CHECK(args[5]->IsBoolean());
    produce_cached_data = args[5]->IsTrue();
    if (!args[6]->IsUndefined()) {
      CHECK(args[6]->IsObject());
      ContextifyContext* sandbox =
          ContextifyContext::ContextFromContextifiedSandbox(
              env, args[6].As<Object>());
      CHECK_NOT_NULL(sandbox);
      parsing_context = sandbox->context();
    }
    CHECK(args[7]->IsSymbol());
    id_symbol = args[7].As<Symbol>();
  }

  ContextifyScript* contextify_script = New(env, args.This());

  if (*TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
          TRACING_CATEGORY_NODE2(vm, script)) != 0) {
    Utf8Value fn(isolate, filename);
    TRACE_EVENT_BEGIN1(TRACING_CATEGORY_NODE2(vm, script),
                       "ContextifyScript::New",
                       "filename",
                       TRACE_STR_COPY(*fn));
  }

  ScriptCompiler::CachedData* cached_data = nullptr;
  if (!cached_data_buf.IsEmpty()) {
    uint8_t* data = static_cast<uint8_t*>(cached_data_buf->Buffer()->Data());
    cached_data = new ScriptCompiler::CachedData(
        data + cached_data_buf->ByteOffset(), cached_data_buf->ByteLength());
  }

  Local<PrimitiveArray> host_defined_options =
      PrimitiveArray::New(isolate, loader::HostDefinedOptions::kLength);
  host_defined_options->Set(
      isolate, loader::HostDefinedOptions::kID, id_symbol);

  ScriptOrigin origin(filename,
                      line_offset,     // line offset
                      column_offset,   // column offset
                      true,            // is cross origin
                      -1,              // script id
                      Local<Value>(),  // source map URL
                      false,           // is opaque (?)
                      false,           // is WASM
                      false,           // is ES Module
                      host_defined_options);
  ScriptCompiler::Source source(code, origin, cached_data);
  ScriptCompiler::CompileOptions compile_options =
      ScriptCompiler::kNoCompileOptions;

  if (source.GetCachedData() != nullptr)
    compile_options = ScriptCompiler::kConsumeCodeCache;

  TryCatchScope try_catch(env);
  ShouldNotAbortOnUncaughtScope no_abort_scope(env);
  Context::Scope scope(parsing_context);

  MaybeLocal<UnboundScript> maybe_v8_script =
      ScriptCompiler::CompileUnboundScript(isolate, &source, compile_options);

  Local<UnboundScript> v8_script;
  if (!maybe_v8_script.ToLocal(&v8_script)) {
    errors::DecorateErrorStack(env, try_catch);
    no_abort_scope.Close();
    if (!try_catch.HasTerminated())
      try_catch.ReThrow();
    TRACE_EVENT_END0(TRACING_CATEGORY_NODE2(vm, script),
                     "ContextifyScript::New");
    return;
  }

  contextify_script->set_unbound_script(v8_script);

  std::unique_ptr<ScriptCompiler::CachedData> new_cached_data;
  if (produce_cached_data) {
    new_cached_data.reset(ScriptCompiler::CreateCodeCache(v8_script));
  }

  auto self = args.This();

  if (contextify_script->object()
          ->SetPrivate(context, env->host_defined_option_symbol(), id_symbol)
          .IsNothing()) {
    return;
  }
  if (StoreCodeCacheResult(env,
                           self,
                           compile_options,
                           source,
                           produce_cached_data,
                           std::move(new_cached_data))
          .IsNothing()) {
    return;
  }
  if (self->Set(env->context(),
                env->source_url_string(),
                v8_script->GetSourceURL())
          .IsNothing()) {
    return;
  }
  if (self->Set(env->context(),
                env->source_map_url_string(),
                v8_script->GetSourceMappingURL())
          .IsNothing()) {
    return;
  }

  TRACE_EVENT_END0(TRACING_CATEGORY_NODE2(vm, script), "ContextifyScript::New");
}

Maybe<void> StoreCodeCacheResult(
    Environment* env,
    Local<Object> target,
    ScriptCompiler::CompileOptions compile_options,
    const v8::ScriptCompiler::Source& source,
    bool produce_cached_data,
    std::unique_ptr<ScriptCompiler::CachedData> new_cached_data) {
  Local<Context> context;
  if (!target->GetCreationContext().ToLocal(&context)) {
    return Nothing<void>();
  }
  if (compile_options == ScriptCompiler::kConsumeCodeCache) {
    if (target
            ->Set(
                context,
                env->cached_data_rejected_string(),
                Boolean::New(env->isolate(), source.GetCachedData()->rejected))
            .IsNothing()) {
      return Nothing<void>();
    }
  }
  if (produce_cached_data) {
    bool cached_data_produced = new_cached_data != nullptr;
    if (cached_data_produced) {
      Local<Object> buf;
      if (!Buffer::Copy(env,
                        reinterpret_cast<const char*>(new_cached_data->data),
                        new_cached_data->length)
               .ToLocal(&buf) ||
          target->Set(context, env->cached_data_string(), buf).IsNothing() ||
          target
              ->Set(context,
                    env->cached_data_produced_string(),
                    Boolean::New(env->isolate(), cached_data_produced))
              .IsNothing()) {
        return Nothing<void>();
      }
    }
  }
  return JustVoid();
}

bool ContextifyScript::InstanceOf(Environment* env,
                                  const Local<Value>& value) {
  return !value.IsEmpty() &&
         env->script_context_constructor_template()->HasInstance(value);
}

void ContextifyScript::CreateCachedData(
    const FunctionCallbackInfo<Value>& args) {
  Environment* env = Environment::GetCurrent(args);
  ContextifyScript* wrapped_script;
  ASSIGN_OR_RETURN_UNWRAP_CPPGC(&wrapped_script, args.This());
  std::unique_ptr<ScriptCompiler::CachedData> cached_data(
      ScriptCompiler::CreateCodeCache(wrapped_script->unbound_script()));

  auto maybeRet = ([&] {
    if (!cached_data) {
      return Buffer::New(env, 0);
    }
    return Buffer::Copy(env,
                        reinterpret_cast<const char*>(cached_data->data),
                        cached_data->length);
  })();

  Local<Object> ret;
  if (maybeRet.ToLocal(&ret)) {
    args.GetReturnValue().Set(ret);
  }
}

void ContextifyScript::RunInContext(const FunctionCallbackInfo<Value>& args) {
  Environment* env = Environment::GetCurrent(args);
  ContextifyScript* wrapped_script;
  ASSIGN_OR_RETURN_UNWRAP_CPPGC(&wrapped_script, args.This());

  CHECK_EQ(args.Length(), 5);
  CHECK(args[0]->IsObject() || args[0]->IsNull());

  Local<Context> context;
  v8::MicrotaskQueue* microtask_queue = nullptr;

  if (args[0]->IsObject()) {
    Local<Object> sandbox = args[0].As<Object>();
    // Get the context from the sandbox
    ContextifyContext* contextify_context =
        ContextifyContext::ContextFromContextifiedSandbox(env, sandbox);
    CHECK_NOT_NULL(contextify_context);
    CHECK_EQ(contextify_context->env(), env);

    context = contextify_context->context();
    if (context.IsEmpty()) return;

    microtask_queue = contextify_context->microtask_queue();
  } else {
    context = env->context();
  }

  TRACE_EVENT0(TRACING_CATEGORY_NODE2(vm, script), "RunInContext");

  CHECK(args[1]->IsNumber());
  int64_t timeout;
  if (!args[1]->IntegerValue(env->context()).To(&timeout)) {
    return;
  }

  CHECK(args[2]->IsBoolean());
  bool display_errors = args[2]->IsTrue();

  CHECK(args[3]->IsBoolean());
  bool break_on_sigint = args[3]->IsTrue();

  CHECK(args[4]->IsBoolean());
  bool break_on_first_line = args[4]->IsTrue();

  // Do the eval within the context
  EvalMachine(context,
              env,
              timeout,
              display_errors,
              break_on_sigint,
              break_on_first_line,
              microtask_queue,
              args);
}

bool ContextifyScript::EvalMachine(Local<Context> context,
                                   Environment* env,
                                   const int64_t timeout,
                                   const bool display_errors,
                                   const bool break_on_sigint,
                                   const bool break_on_first_line,
                                   MicrotaskQueue* mtask_queue,
                                   const FunctionCallbackInfo<Value>& args) {
  Context::Scope context_scope(context);

  if (!env->can_call_into_js())
    return false;
  if (!ContextifyScript::InstanceOf(env, args.This())) {
    THROW_ERR_INVALID_THIS(
        env,
        "Script methods can only be called on script instances.");
    return false;
  }

  TryCatchScope try_catch(env);
  ContextifyScript* wrapped_script;
  ASSIGN_OR_RETURN_UNWRAP_CPPGC(&wrapped_script, args.This(), false);
  Local<Script> script =
      wrapped_script->unbound_script()->BindToCurrentContext();

#if HAVE_INSPECTOR
  if (break_on_first_line) {
    if (!env->permission()->is_granted(env,
                                       permission::PermissionScope::kInspector,
                                       "PauseOnNextJavascriptStatement"))
        [[unlikely]] {
      node::permission::Permission::ThrowAccessDenied(
          env,
          permission::PermissionScope::kInspector,
          "PauseOnNextJavascriptStatement");
      if (display_errors) {
        // We should decorate non-termination exceptions
        errors::DecorateErrorStack(env, try_catch);
      }
      try_catch.ReThrow();
      return false;
    }
    env->inspector_agent()->PauseOnNextJavascriptStatement("Break on start");
  }
#endif

  MaybeLocal<Value> result;
  bool timed_out = false;
  bool received_signal = false;
  {
    auto wd = timeout != -1 ? std::make_optional<Watchdog>(
                                  env->isolate(), timeout, &timed_out)
                            : std::nullopt;
    auto swd = break_on_sigint ? std::make_optional<SigintWatchdog>(
                                     env->isolate(), &received_signal)
                               : std::nullopt;

    result = script->Run(context);
    if (!result.IsEmpty() && mtask_queue != nullptr)
      mtask_queue->PerformCheckpoint(env->isolate());
  }

  // Convert the termination exception into a regular exception.
  if (timed_out || received_signal) {
    if (!env->is_main_thread() && env->is_stopping())
      return false;
    env->isolate()->CancelTerminateExecution();
    // It is possible that execution was terminated by another timeout in
    // which this timeout is nested, so check whether one of the watchdogs
    // from this invocation is responsible for termination.
    if (timed_out) {
      node::THROW_ERR_SCRIPT_EXECUTION_TIMEOUT(env, timeout);
    } else if (received_signal) {
      node::THROW_ERR_SCRIPT_EXECUTION_INTERRUPTED(env);
    }
  }

  if (try_catch.HasCaught()) {
    if (!timed_out && !received_signal && display_errors) {
      // We should decorate non-termination exceptions
      errors::DecorateErrorStack(env, try_catch);
    }

    // If there was an exception thrown during script execution, re-throw it.
    // If one of the above checks threw, re-throw the exception instead of
    // letting try_catch catch it.
    // If execution has been terminated, but not by one of the watchdogs from
    // this invocation, this will re-throw a `null` value.
    if (!try_catch.HasTerminated())
      try_catch.ReThrow();

    return false;
  }

  // We checked for res being empty previously so this is a bit redundant
  // but still safer than using ToLocalChecked.
  Local<Value> res;
  if (!result.ToLocal(&res)) return false;

  args.GetReturnValue().Set(res);
  return true;
}

Local<UnboundScript> ContextifyScript::unbound_script() const {
  return script_.Get(env()->isolate());
}

void ContextifyScript::set_unbound_script(Local<UnboundScript> script) {
  script_.Reset(env()->isolate(), script);
}

void ContextifyScript::Trace(cppgc::Visitor* visitor) const {
  CppgcMixin::Trace(visitor);
  visitor->Trace(script_);
}

ContextifyScript::ContextifyScript(Environment* env, Local<Object> object) {
  CppgcMixin::Wrap(this, env, object);
}

ContextifyScript::~ContextifyScript() {}

void ContextifyFunction::RegisterExternalReferences(
    ExternalReferenceRegistry* registry) {
  registry->Register(CompileFunction);
}

void ContextifyFunction::CreatePerIsolateProperties(
    IsolateData* isolate_data, Local<ObjectTemplate> target) {
  Isolate* isolate = isolate_data->isolate();

  SetMethod(isolate, target, "compileFunction", CompileFunction);
}

void ContextifyFunction::CompileFunction(
    const FunctionCallbackInfo<Value>& args) {
  Environment* env = Environment::GetCurrent(args);
  Isolate* isolate = env->isolate();
  Local<Context> context = env->context();

  // Argument 1: source code
  CHECK(args[0]->IsString());
  Local<String> code = args[0].As<String>();

  // Argument 2: filename
  CHECK(args[1]->IsString());
  Local<String> filename = args[1].As<String>();

  // Argument 3: line offset
  CHECK(args[2]->IsNumber());
  int line_offset = args[2].As<Int32>()->Value();

  // Argument 4: column offset
  CHECK(args[3]->IsNumber());
  int column_offset = args[3].As<Int32>()->Value();

  // Argument 5: cached data (optional)
  Local<ArrayBufferView> cached_data_buf;
  if (!args[4]->IsUndefined()) {
    CHECK(args[4]->IsArrayBufferView());
    cached_data_buf = args[4].As<ArrayBufferView>();
  }

  // Argument 6: produce cache data
  CHECK(args[5]->IsBoolean());
  bool produce_cached_data = args[5]->IsTrue();

  // Argument 7: parsing context (optional)
  Local<Context> parsing_context;
  if (!args[6]->IsUndefined()) {
    CHECK(args[6]->IsObject());
    ContextifyContext* sandbox =
        ContextifyContext::ContextFromContextifiedSandbox(
            env, args[6].As<Object>());
    CHECK_NOT_NULL(sandbox);
    parsing_context = sandbox->context();
  } else {
    parsing_context = context;
  }

  // Argument 8: context extensions (optional)
  Local<Array> context_extensions_buf;
  if (!args[7]->IsUndefined()) {
    CHECK(args[7]->IsArray());
    context_extensions_buf = args[7].As<Array>();
  }

  // Argument 9: params for the function (optional)
  Local<Array> params_buf;
  if (!args[8]->IsUndefined()) {
    CHECK(args[8]->IsArray());
    params_buf = args[8].As<Array>();
  }

  // Argument 10: host-defined option symbol
  CHECK(args[9]->IsSymbol());
  Local<Symbol> id_symbol = args[9].As<Symbol>();

  // Read cache from cached data buffer
  ScriptCompiler::CachedData* cached_data = nullptr;
  if (!cached_data_buf.IsEmpty()) {
    uint8_t* data = static_cast<uint8_t*>(cached_data_buf->Buffer()->Data());
    cached_data = new ScriptCompiler::CachedData(
      data + cached_data_buf->ByteOffset(), cached_data_buf->ByteLength());
  }

  Local<PrimitiveArray> host_defined_options =
      loader::ModuleWrap::GetHostDefinedOptions(isolate, id_symbol);

  ScriptOrigin origin(filename,
                      line_offset,     // line offset
                      column_offset,   // column offset
                      true,            // is cross origin
                      -1,              // script id
                      Local<Value>(),  // source map URL
                      false,           // is opaque (?)
                      false,           // is WASM
                      false,           // is ES Module
                      host_defined_options);
  ScriptCompiler::Source source(code, origin, cached_data);

  ScriptCompiler::CompileOptions options;
  if (source.GetCachedData() != nullptr) {
    options = ScriptCompiler::kConsumeCodeCache;
  } else {
    options = ScriptCompiler::kNoCompileOptions;
  }

  Context::Scope scope(parsing_context);

  // Read context extensions from buffer
  LocalVector<Object> context_extensions(isolate);
  if (!context_extensions_buf.IsEmpty()) {
    for (uint32_t n = 0; n < context_extensions_buf->Length(); n++) {
      Local<Value> val;
      if (!context_extensions_buf->Get(context, n).ToLocal(&val)) return;
      CHECK(val->IsObject());
      context_extensions.push_back(val.As<Object>());
    }
  }

  // Read params from params buffer
  LocalVector<String> params(isolate);
  if (!params_buf.IsEmpty()) {
    for (uint32_t n = 0; n < params_buf->Length(); n++) {
      Local<Value> val;
      if (!params_buf->Get(context, n).ToLocal(&val)) return;
      CHECK(val->IsString());
      params.push_back(val.As<String>());
    }
  }

  TryCatchScope try_catch(env);
  MaybeLocal<Object> maybe_result =
      CompileFunctionAndCacheResult(env,
                                    parsing_context,
                                    &source,
                                    params,
                                    context_extensions,
                                    options,
                                    produce_cached_data,
                                    id_symbol,
                                    try_catch);
  Local<Object> result;
  if (!maybe_result.ToLocal(&result)) {
    CHECK(try_catch.HasCaught());
    try_catch.ReThrow();
    return;
  }
  args.GetReturnValue().Set(result);
}

static LocalVector<String> GetCJSParameters(IsolateData* data) {
  LocalVector<String> result(data->isolate(),
                             {
                                 data->exports_string(),
                                 data->require_string(),
                                 data->module_string(),
                                 data->__filename_string(),
                                 data->__dirname_string(),
                             });
  return result;
}

MaybeLocal<Object> ContextifyFunction::CompileFunctionAndCacheResult(
    Environment* env,
    Local<Context> parsing_context,
    ScriptCompiler::Source* source,
    LocalVector<String> params,
    LocalVector<Object> context_extensions,
    ScriptCompiler::CompileOptions options,
    bool produce_cached_data,
    Local<Symbol> id_symbol,
    const TryCatchScope& try_catch) {
  MaybeLocal<Function> maybe_fn = ScriptCompiler::CompileFunction(
      parsing_context,
      source,
      params.size(),
      params.data(),
      context_extensions.size(),
      context_extensions.data(),
      options,
      v8::ScriptCompiler::NoCacheReason::kNoCacheNoReason);

  Local<Function> fn;
  if (!maybe_fn.ToLocal(&fn)) {
    CHECK(try_catch.HasCaught());
    if (!try_catch.HasTerminated()) {
      errors::DecorateErrorStack(env, try_catch);
    }
    return {};
  }

  Local<Context> context = env->context();
  if (fn->SetPrivate(context, env->host_defined_option_symbol(), id_symbol)
          .IsNothing()) {
    return {};
  }

  auto tmpl = env->compiled_function_template();
  if (tmpl.IsEmpty()) {
    static constexpr std::string_view names[] = {
        "function",
        "sourceURL",
        "sourceMapURL",
        "cachedDataRejected",
        "cachedDataProduced",
        "cachedData",
    };
    tmpl = DictionaryTemplate::New(env->isolate(), names);
    env->set_compiled_function_template(tmpl);
  }

  auto scriptOrigin = fn->GetScriptOrigin();
  MaybeLocal<Value> values[] = {
      fn,
      // ScriptOrigin::ResourceName() returns SourceURL magic comment content if
      // present.
      scriptOrigin.ResourceName(),
      scriptOrigin.SourceMapUrl(),
      // These are conditionally filled in by StoreCodeCacheResult below.
      Undefined(env->isolate()),  // cachedDataRejected
      Undefined(env->isolate()),  // cachedDataProduced
      Undefined(env->isolate()),  // cachedData
  };

  Local<Object> result;
  if (!NewDictionaryInstance(env->context(), tmpl, values).ToLocal(&result)) {
    return {};
  }

  std::unique_ptr<ScriptCompiler::CachedData> new_cached_data;
  if (produce_cached_data) {
    new_cached_data.reset(ScriptCompiler::CreateCodeCacheForFunction(fn));
  }
  if (StoreCodeCacheResult(env,
                           result,
                           options,
                           *source,
                           produce_cached_data,
                           std::move(new_cached_data))
          .IsNothing()) {
    return {};
  }

  return result;
}

// When compiling as CommonJS source code that contains ESM syntax, the
// following error messages are returned:
// - `import` statements: "Cannot use import statement outside a module"
// - `export` statements: "Unexpected token 'export'"
// - `import.meta` references: "Cannot use 'import.meta' outside a module"
// Dynamic `import()` is permitted in CommonJS, so it does not error.
// While top-level `await` is not permitted in CommonJS, it returns the same
// error message as when `await` is used in a sync function, so we don't use it
// as a disambiguation.
static const auto esm_syntax_error_messages = std::array<std::string_view, 3>{
    "Cannot use import statement outside a module",  // `import` statements
    "Unexpected token 'export'",                     // `export` statements
    "Cannot use 'import.meta' outside a module"};    // `import.meta` references

// Another class of error messages that we need to check for are syntax errors
// where the syntax throws when parsed as CommonJS but succeeds when parsed as
// ESM. So far, the cases we've found are:
// - CommonJS module variables (`module`, `exports`, `require`, `__filename`,
//   `__dirname`): if the user writes code such as `const module =` in the top
//   level of a CommonJS module, it will throw a syntax error; but the same
//   code is valid in ESM.
// - Top-level `await`: if the user writes `await` at the top level of a
//   CommonJS module, it will throw a syntax error; but the same code is valid
//   in ESM.
static const auto throws_only_in_cjs_error_messages =
    std::array<std::string_view, 6>{
        "Identifier 'module' has already been declared",
        "Identifier 'exports' has already been declared",
        "Identifier 'require' has already been declared",
        "Identifier '__filename' has already been declared",
        "Identifier '__dirname' has already been declared",
        "await is only valid in async functions and "
        "the top level bodies of modules"};

static const auto maybe_top_level_await_errors =
    std::array<std::string_view, 2>{
        "missing ) after argument list",  // example: `func(await 1);`
        "SyntaxError: Unexpected"         // example: `if(await 1)`
    };

// If cached_data is provided, it would be used for the compilation and
// the on-disk compilation cache from NODE_COMPILE_CACHE (if configured)
// would be ignored.
static MaybeLocal<Function> CompileFunctionForCJSLoader(
    Environment* env,
    Local<Context> context,
    Local<String> code,
    Local<String> filename,
    bool* cache_rejected,
    bool is_cjs_scope,
    ScriptCompiler::CachedData* cached_data) {
  Isolate* isolate = Isolate::GetCurrent();
  EscapableHandleScope scope(isolate);

  Local<Symbol> symbol = env->vm_dynamic_import_default_internal();
  Local<PrimitiveArray> hdo =
      loader::ModuleWrap::GetHostDefinedOptions(isolate, symbol);
  ScriptOrigin origin(filename,
                      0,               // line offset
                      0,               // column offset
                      true,            // is cross origin
                      -1,              // script id
                      Local<Value>(),  // source map URL
                      false,           // is opaque
                      false,           // is WASM
                      false,           // is ES Module
                      hdo);

  CompileCacheEntry* cache_entry = nullptr;
  if (cached_data == nullptr && env->use_compile_cache()) {
    cache_entry = env->compile_cache_handler()->GetOrInsert(
        code, filename, CachedCodeType::kCommonJS);
  }
  if (cache_entry != nullptr && cache_entry->cache != nullptr) {
    // source will take ownership of cached_data.
    cached_data = cache_entry->CopyCache();
  }

  ScriptCompiler::Source source(code, origin, cached_data);
  ScriptCompiler::CompileOptions options;
  if (cached_data == nullptr) {
    options = ScriptCompiler::kNoCompileOptions;
  } else {
    options = ScriptCompiler::kConsumeCodeCache;
  }

  LocalVector<String> params(isolate);
  if (is_cjs_scope) {
    params = GetCJSParameters(env->isolate_data());
  }
  MaybeLocal<Function> maybe_fn = ScriptCompiler::CompileFunction(
      context,
      &source,
      params.size(),
      params.data(),
      0,       /* context extensions size */
      nullptr, /* context extensions data */
      // TODO(joyeecheung): allow optional eager compilation.
      options);

  Local<Function> fn;
  if (!maybe_fn.ToLocal(&fn)) {
    return scope.EscapeMaybe(MaybeLocal<Function>());
  }

  if (options == ScriptCompiler::kConsumeCodeCache) {
    *cache_rejected = source.GetCachedData()->rejected;
  }
  if (cache_entry != nullptr) {
    env->compile_cache_handler()->MaybeSave(cache_entry, fn, *cache_rejected);
  }
  return scope.Escape(fn);
}

static std::string GetRequireEsmWarning(Local<String> filename) {
  Isolate* isolate = Isolate::GetCurrent();
  Utf8Value filename_utf8(isolate, filename);

  std::string warning_message =
      "Failed to load the ES module: " + filename_utf8.ToString() +
      ". Make sure to set \"type\": \"module\" in the nearest package.json "
      "file "
      "or use the .mjs extension.";
  return warning_message;
}

static bool warned_about_require_esm = false;

static bool ShouldRetryAsESM(Realm* realm,
                             Local<String> message,
                             Local<String> code,
                             Local<String> resource_name);

static void CompileFunctionForCJSLoader(
    const FunctionCallbackInfo<Value>& args) {
  CHECK(args[0]->IsString());
  CHECK(args[1]->IsString());
  CHECK(args[2]->IsBoolean());
  CHECK(args[3]->IsBoolean());
  Local<String> code = args[0].As<String>();
  Local<String> filename = args[1].As<String>();
  bool is_sea_main = args[2].As<Boolean>()->Value();
  bool should_detect_module = args[3].As<Boolean>()->Value();

  Isolate* isolate = args.GetIsolate();
  Local<Context> context = isolate->GetCurrentContext();
  Realm* realm = Realm::GetCurrent(context);
  Environment* env = realm->env();

  bool cache_rejected = false;
  Local<Function> fn;
  Local<Value> cjs_exception;
  Local<Message> cjs_message;

  ScriptCompiler::CachedData* cached_data = nullptr;
#ifndef DISABLE_SINGLE_EXECUTABLE_APPLICATION
  if (is_sea_main) {
    sea::SeaResource sea = sea::FindSingleExecutableResource();
    // Use the "main" field in SEA config for the filename.
    Local<Value> filename_from_sea;
    if (!ToV8Value(context, sea.code_path).ToLocal(&filename_from_sea)) {
      return;
    }
    filename = filename_from_sea.As<String>();
    if (sea.use_code_cache()) {
      std::string_view data = sea.code_cache.value();
      cached_data = new ScriptCompiler::CachedData(
          reinterpret_cast<const uint8_t*>(data.data()),
          static_cast<int>(data.size()),
          v8::ScriptCompiler::CachedData::BufferNotOwned);
    }
  }
#endif

  {
    ShouldNotAbortOnUncaughtScope no_abort_scope(realm->env());
    TryCatchScope try_catch(env);
    if (!CompileFunctionForCJSLoader(
             env, context, code, filename, &cache_rejected, true, cached_data)
             .ToLocal(&fn)) {
      CHECK(try_catch.HasCaught());
      CHECK(!try_catch.HasTerminated());
      cjs_exception = try_catch.Exception();
      cjs_message = try_catch.Message();
      errors::DecorateErrorStack(env, cjs_exception, cjs_message);
    }
  }

  bool can_parse_as_esm = false;
  if (!cjs_exception.IsEmpty()) {
    // Use the URL to match what would be used in the origin if it's going to
    // be reparsed as ESM.
    Utf8Value filename_utf8(isolate, filename);
    std::string url = url::FromFilePath(filename_utf8.ToStringView());
    Local<Value> url_value;
    if (!ToV8Value(context, url).ToLocal(&url_value)) {
      return;
    }
    can_parse_as_esm = ShouldRetryAsESM(
        realm, cjs_message->Get(), code, url_value.As<String>());
    if (!can_parse_as_esm) {
      // The syntax error is not related to ESM, throw the original error.
      isolate->ThrowException(cjs_exception);
      return;
    }

    if (!should_detect_module) {
      bool should_throw = true;
      if (!warned_about_require_esm) {
        // This needs to call process.emit('warning') in JS which can throw if
        // the user listener throws. In that case, don't try to throw the syntax
        // error.
        std::string warning_message = GetRequireEsmWarning(filename);
        should_throw = ProcessEmitWarningSync(env, warning_message).IsJust();
      }
      if (should_throw) {
        isolate->ThrowException(cjs_exception);
      }
      return;
    }
  }

  auto tmpl = env->compiled_function_cjs_template();
  if (tmpl.IsEmpty()) {
    static constexpr std::string_view names[] = {
        "cachedDataRejected",
        "sourceMapURL",
        "sourceURL",
        "function",
        "canParseAsESM",
    };
    tmpl = DictionaryTemplate::New(isolate, names);
    env->set_compiled_function_cjs_template(tmpl);
  }

  Local<Value> undefined = v8::Undefined(isolate);

  MaybeLocal<Value> values[] = {
      Boolean::New(isolate, cache_rejected),
      fn.IsEmpty() ? undefined : fn->GetScriptOrigin().SourceMapUrl(),
      // ScriptOrigin::ResourceName() returns SourceURL magic comment content if
      // present.
      fn.IsEmpty() ? undefined : fn->GetScriptOrigin().ResourceName(),
      fn.IsEmpty() ? undefined : fn.As<Value>(),
      Boolean::New(isolate, can_parse_as_esm),
  };
  Local<Object> result;
  if (NewDictionaryInstance(env->context(), tmpl, values).ToLocal(&result)) {
    args.GetReturnValue().Set(result);
  }
}

bool ShouldRetryAsESM(Realm* realm,
                      Local<String> message,
                      Local<String> code,
                      Local<String> resource_name) {
  Isolate* isolate = realm->isolate();

  Utf8Value message_value(isolate, message);
  auto message_view = message_value.ToStringView();

  // These indicates that the file contains syntaxes that are only valid in
  // ESM. So it must be true.
  for (const auto& error_message : esm_syntax_error_messages) {
    if (message_view.find(error_message) != std::string_view::npos) {
      return true;
    }
  }

  // Check if the error message is allowed in ESM but not in CommonJS. If it
  // is the case, let's check if file can be compiled as ESM.
  bool maybe_valid_in_esm = false;
  for (const auto& error_message : throws_only_in_cjs_error_messages) {
    if (message_view.find(error_message) != std::string_view::npos) {
      maybe_valid_in_esm = true;
      break;
    }
  }

  for (const auto& error_message : maybe_top_level_await_errors) {
    if (message_view.find(error_message) != std::string_view::npos) {
      // If the error message is related to top-level await, we can try to
      // compile it as ESM.
      maybe_valid_in_esm = true;
      break;
    }
  }

  if (!maybe_valid_in_esm) {
    return false;
  }

  bool cache_rejected = false;
  TryCatchScope try_catch(realm->env());
  ShouldNotAbortOnUncaughtScope no_abort_scope(realm->env());
  Local<v8::Module> module;
  Local<PrimitiveArray> hdo = loader::ModuleWrap::GetHostDefinedOptions(
      isolate, realm->isolate_data()->source_text_module_default_hdo());
  if (loader::ModuleWrap::CompileSourceTextModule(
          realm, code, resource_name, 0, 0, hdo, std::nullopt, &cache_rejected)
          .ToLocal(&module)) {
    return true;
  }

  return false;
}

static void ContainsModuleSyntax(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();
  Local<Context> context = isolate->GetCurrentContext();
  Realm* realm = Realm::GetCurrent(context);
  Environment* env = realm->env();

  CHECK_GE(args.Length(), 2);

  // Argument 1: source code
  CHECK(args[0]->IsString());
  Local<String> code = args[0].As<String>();

  // Argument 2: filename
  CHECK(args[1]->IsString());
  Local<String> filename = args[1].As<String>();

  // Argument 3: resource name (URL for ES module).
  Local<String> resource_name = filename;
  if (args[2]->IsString()) {
    resource_name = args[2].As<String>();
  }
  // Argument 4: flag to indicate if CJS variables should not be in scope
  // (they should be for normal CommonJS modules, but not for the
  // CommonJS eval scope).
  bool cjs_var = !args[3]->IsString();

  bool cache_rejected = false;
  Local<String> message;
  {
    Local<Function> fn;
    TryCatchScope try_catch(env);
    ShouldNotAbortOnUncaughtScope no_abort_scope(env);
    if (CompileFunctionForCJSLoader(
            env, context, code, filename, &cache_rejected, cjs_var, nullptr)
            .ToLocal(&fn)) {
      args.GetReturnValue().Set(false);
      return;
    }
    CHECK(try_catch.HasCaught());
    message = try_catch.Message()->Get();
  }

  bool result = ShouldRetryAsESM(realm, message, code, resource_name);
  args.GetReturnValue().Set(result);
}

static void StartSigintWatchdog(const FunctionCallbackInfo<Value>& args) {
  int ret = SigintWatchdogHelper::GetInstance()->Start();
  args.GetReturnValue().Set(ret == 0);
}

static void StopSigintWatchdog(const FunctionCallbackInfo<Value>& args) {
  bool had_pending_signals = SigintWatchdogHelper::GetInstance()->Stop();
  args.GetReturnValue().Set(had_pending_signals);
}

static void WatchdogHasPendingSigint(const FunctionCallbackInfo<Value>& args) {
  bool ret = SigintWatchdogHelper::GetInstance()->HasPendingSignal();
  args.GetReturnValue().Set(ret);
}

static void MeasureMemory(const FunctionCallbackInfo<Value>& args) {
  CHECK(args[0]->IsInt32());
  CHECK(args[1]->IsInt32());
  int32_t mode = args[0].As<v8::Int32>()->Value();
  int32_t execution = args[1].As<v8::Int32>()->Value();
  Isolate* isolate = args.GetIsolate();

  Local<Context> current_context = isolate->GetCurrentContext();
  Local<Promise::Resolver> resolver;
  if (!Promise::Resolver::New(current_context).ToLocal(&resolver)) return;
  std::unique_ptr<v8::MeasureMemoryDelegate> delegate =
      v8::MeasureMemoryDelegate::Default(
          isolate,
          current_context,
          resolver,
          static_cast<v8::MeasureMemoryMode>(mode));
  isolate->MeasureMemory(std::move(delegate),
                         static_cast<v8::MeasureMemoryExecution>(execution));
  Local<Promise> promise = resolver->GetPromise();

  args.GetReturnValue().Set(promise);
}

void CreatePerIsolateProperties(IsolateData* isolate_data,
                                Local<ObjectTemplate> target) {
  Isolate* isolate = isolate_data->isolate();

  ContextifyContext::CreatePerIsolateProperties(isolate_data, target);
  ContextifyScript::CreatePerIsolateProperties(isolate_data, target);
  ContextifyFunction::CreatePerIsolateProperties(isolate_data, target);

  SetMethod(isolate, target, "startSigintWatchdog", StartSigintWatchdog);
  SetMethod(isolate, target, "stopSigintWatchdog", StopSigintWatchdog);
  // Used in tests.
  SetMethodNoSideEffect(
      isolate, target, "watchdogHasPendingSigint", WatchdogHasPendingSigint);

  SetMethod(isolate, target, "measureMemory", MeasureMemory);
  SetMethod(isolate,
            target,
            "compileFunctionForCJSLoader",
            CompileFunctionForCJSLoader);

  SetMethod(isolate, target, "containsModuleSyntax", ContainsModuleSyntax);
}

static void CreatePerContextProperties(Local<Object> target,
                                       Local<Value> unused,
                                       Local<Context> context,
                                       void* priv) {
  Environment* env = Environment::GetCurrent(context);
  Isolate* isolate = env->isolate();

  Local<Object> constants = Object::New(env->isolate());
  Local<Object> measure_memory = Object::New(env->isolate());
  Local<Object> memory_execution = Object::New(env->isolate());

  {
    Local<Object> memory_mode = Object::New(env->isolate());
    MeasureMemoryMode SUMMARY = MeasureMemoryMode::kSummary;
    MeasureMemoryMode DETAILED = MeasureMemoryMode::kDetailed;
    NODE_DEFINE_CONSTANT(memory_mode, SUMMARY);
    NODE_DEFINE_CONSTANT(memory_mode, DETAILED);
    READONLY_PROPERTY(measure_memory, "mode", memory_mode);
  }

  {
    MeasureMemoryExecution DEFAULT = MeasureMemoryExecution::kDefault;
    MeasureMemoryExecution EAGER = MeasureMemoryExecution::kEager;
    NODE_DEFINE_CONSTANT(memory_execution, DEFAULT);
    NODE_DEFINE_CONSTANT(memory_execution, EAGER);
    READONLY_PROPERTY(measure_memory, "execution", memory_execution);
  }

  READONLY_PROPERTY(constants, "measureMemory", measure_memory);

  target->Set(context, env->constants_string(), constants).Check();
}

void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
  ContextifyContext::RegisterExternalReferences(registry);
  ContextifyScript::RegisterExternalReferences(registry);
  ContextifyFunction::RegisterExternalReferences(registry);

  registry->Register(CompileFunctionForCJSLoader);
  registry->Register(StartSigintWatchdog);
  registry->Register(StopSigintWatchdog);
  registry->Register(WatchdogHasPendingSigint);
  registry->Register(MeasureMemory);
  registry->Register(ContainsModuleSyntax);
}
}  // namespace contextify
}  // namespace node

NODE_BINDING_CONTEXT_AWARE_INTERNAL(
    contextify, node::contextify::CreatePerContextProperties)
NODE_BINDING_PER_ISOLATE_INIT(contextify,
                              node::contextify::CreatePerIsolateProperties)
NODE_BINDING_EXTERNAL_REFERENCE(contextify,
                                node::contextify::RegisterExternalReferences)
