current commit
261019.10 · module: add --experimental-strip-private-modules
#ifndef SRC_NODE_MODULES_H_
#define SRC_NODE_MODULES_H_

#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS

#include "node.h"
#include "node_snapshotable.h"
#include "simdjson.h"
#include "util.h"
#include "v8-fast-api-calls.h"
#include "v8.h"

#include <filesystem>
#include <optional>
#include <string>
#include <string_view>
#include <unordered_map>

namespace node {
class ExternalReferenceRegistry;

namespace modules {

class BindingData : public SnapshotableObject {
 public:
  using InternalFieldInfo = InternalFieldInfoBase;

  struct PackageConfig {
    std::string file_path;
    std::optional<std::string> name;
    std::optional<std::string> main;
    std::string type = "none";
    std::optional<std::string> exports;
    std::optional<std::string> imports;
    std::optional<std::string> scripts;
    std::optional<bool> is_private;
    std::string raw_json;

    v8::Local<v8::Array> Serialize(Realm* realm) const;
  };

  struct ErrorContext {
    std::optional<std::string> base;
    std::string specifier;
    bool is_esm;
  };

  BindingData(Realm* realm,
              v8::Local<v8::Object> obj,
              InternalFieldInfo* info = nullptr);
  SERIALIZABLE_OBJECT_METHODS()
  SET_BINDING_ID(modules_binding_data)

  void MemoryInfo(MemoryTracker* tracker) const override;
  SET_SELF_SIZE(BindingData)
  SET_MEMORY_INFO_NAME(BindingData)

  static void ReadPackageJSON(const v8::FunctionCallbackInfo<v8::Value>& args);
  // Like ReadPackageJSON but the caller supplies the raw JSON body.
  // Does not populate the C++ `package_configs_` cache.
  // Signature: parsePackageJSON(source, jsonPath, isESM, base, specifier)
  static void ParsePackageJSONBinding(
      const v8::FunctionCallbackInfo<v8::Value>& args);
  static void GetNearestParentPackageJSON(
      const v8::FunctionCallbackInfo<v8::Value>& args);
  static void GetRootPackageJSON(
      const v8::FunctionCallbackInfo<v8::Value>& args);
  static void GetNearestParentPackageJSONType(
      const v8::FunctionCallbackInfo<v8::Value>& args);
  template <bool return_only_type>
  static void GetPackageScopeConfig(
      const v8::FunctionCallbackInfo<v8::Value>& args);
  static void GetPackageJSONScripts(
      const v8::FunctionCallbackInfo<v8::Value>& args);

  static void CreatePerIsolateProperties(IsolateData* isolate_data,
                                         v8::Local<v8::ObjectTemplate> ctor);
  static void CreatePerContextProperties(v8::Local<v8::Object> target,
                                         v8::Local<v8::Value> unused,
                                         v8::Local<v8::Context> context,
                                         void* priv);
  static void RegisterExternalReferences(ExternalReferenceRegistry* registry);

 private:
  /*
   * This map caches `PackageConfig` values by `package.json` path.
   * An empty optional value indicates that no `package.json` file
   * at the given path exists, which we cache to avoid repeated
   * attempts to open the same non-existent paths.
   */
  std::unordered_map<std::string, std::optional<PackageConfig> >
      package_configs_;
  simdjson::ondemand::parser json_parser;
  static const std::filesystem::path NormalizePath(Realm* realm,
                                                   BufferValue* path_value);
  // returns null on error
  static const PackageConfig* GetPackageJSON(
      Realm* realm,
      std::string_view path,
      ErrorContext* error_context = nullptr);
  // Parses `package_config->raw_json` into `package_config`; caller
  // must set raw_json and file_path first. Returns false and throws
  // ERR_INVALID_PACKAGE_CONFIG on a syntactic error.
  static bool ParsePackageJSON(Realm* realm,
                               PackageConfig* package_config,
                               ErrorContext* error_context);
  static const PackageConfig* TraverseParent(
      Realm* realm, const std::filesystem::path& check_path);
  // Returns the package.json of the package that owns check_path inside the
  // innermost node_modules directory, or null when check_path is not inside
  // node_modules or the package root has no package.json.
  static const PackageConfig* FindNodeModulesPackage(
      Realm* realm, const std::filesystem::path& check_path);
};

}  // namespace modules
}  // namespace node

#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS

#endif  // SRC_NODE_MODULES_H_