Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 20 additions & 5 deletions lib/internal/modules/package_json_reader.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,15 @@ const modulesBinding = internalBinding('modules');
const { resolve, sep } = require('path');
const { kEmptyObject } = require('internal/util');

/**
* @typedef {import('typings/internalBinding/modules').PackageConfig} PackageConfig
* @typedef {import('typings/internalBinding/modules').SerializedPackageConfig} SerializedPackageConfig
*/

/**
* @param {string} path
* @param {import('typings/internalBinding/modules').SerializedPackageConfig} contents
* @returns {import('typings/internalBinding/modules').PackageConfig}
* @param {SerializedPackageConfig} contents
* @returns {PackageConfig}
*/
function deserializePackageJSON(path, contents) {
if (contents === undefined) {
Expand Down Expand Up @@ -75,7 +80,7 @@ function deserializePackageJSON(path, contents) {
* specifier?: URL | string,
* isESM?: boolean,
* }} options
* @returns {import('typings/internalBinding/modules').PackageConfig}
* @returns {PackageConfig}
*/
function read(jsonPath, { base, specifier, isESM } = kEmptyObject) {
// This function will be called by both CJS and ESM, so we need to make sure
Expand Down Expand Up @@ -105,7 +110,7 @@ function readPackage(requestPath) {
* Get the nearest parent package.json file from a given path.
* Return the package.json data and the path to the package.json file, or undefined.
* @param {string} checkPath The path to start searching from.
* @returns {undefined | {data: import('typings/internalBinding/modules').PackageConfig, path: string}}
* @returns {undefined | {data: PackageConfig, path: string}}
*/
function getNearestParentPackageJSON(checkPath) {
const result = modulesBinding.getNearestParentPackageJSON(checkPath);
Expand All @@ -123,10 +128,19 @@ function getNearestParentPackageJSON(checkPath) {
return { data, path };
}

/**
* Find the nearest package.json
* @param {URL['pathname']} origin Where to start searching.
* @returns {URL['pathname']} The fully resolved location of the package.json file.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: Do we need to also make sure this returns a UNC path on Windows? UNC path (the result of toNamespacedPath() is required if the path is extremely long. windows weirdly throws an error if long path feature is not enabled)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* @returns {URL['pathname']} The fully resolved location of the package.json file.
* @returns {URL['pathname'] | undefined} The fully resolved location of the package.json file.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding your question: i have no idea. It sounds like you answered it yourself though (and the answer is "yes").

*/
function findNearestPackageJSON(origin) {
return modulesBinding.findNearestPackageJSON(origin);
}

/**
* Returns the package configuration for the given resolved URL.
* @param {URL | string} resolved - The resolved URL.
* @returns {import('typings/internalBinding/modules').PackageConfig} - The package configuration.
* @returns {PackageConfig} - The package configuration.
*/
function getPackageScopeConfig(resolved) {
const result = modulesBinding.getPackageScopeConfig(`${resolved}`);
Expand Down Expand Up @@ -160,4 +174,5 @@ module.exports = {
getNearestParentPackageJSON,
getPackageScopeConfig,
getPackageType,
findNearestPackageJSON,
};
4 changes: 4 additions & 0 deletions lib/module.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ const {
flushCompileCache,
getCompileCacheDir,
} = require('internal/modules/helpers');
const {
findNearestPackageJSON,
} = require('internal/modules/package_json_reader');

Module.findSourceMap = findSourceMap;
Module.register = register;
Expand All @@ -19,4 +22,5 @@ Module.enableCompileCache = enableCompileCache;
Module.flushCompileCache = flushCompileCache;

Module.getCompileCacheDir = getCompileCacheDir;
Module.findNearestPackageJSON = findNearestPackageJSON;
module.exports = Module;
43 changes: 18 additions & 25 deletions src/node_modules.cc
Original file line number Diff line number Diff line change
Expand Up @@ -313,8 +313,9 @@ const BindingData::PackageConfig* BindingData::TraverseParent(
return nullptr;
}

void BindingData::GetNearestParentPackageJSON(
const v8::FunctionCallbackInfo<v8::Value>& args) {
void BindingData::FindNearestParentPackageJSON(
const v8::FunctionCallbackInfo<v8::Value>& args
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change seems to be unrelated

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically yes, this un-mangling is not required to make the change work.

) {
CHECK_GE(args.Length(), 1);
CHECK(args[0]->IsString());

Expand All @@ -331,41 +332,32 @@ void BindingData::GetNearestParentPackageJSON(
path_value_str.push_back(kPathSeparator);
}

auto package_json =
TraverseParent(realm, std::filesystem::path(path_value_str));
args.GetReturnValue().Set(path_value_str);
}

void BindingData::GetNearestParentPackageJSON(
const v8::FunctionCallbackInfo<v8::Value>& args
) {
auto path = FindNearestParentPackageJSON(args);

auto package_json = TraverseParent(realm, std::filesystem::path(path_value_str));

if (package_json != nullptr) {
args.GetReturnValue().Set(package_json->Serialize(realm));
}
}

void BindingData::GetNearestParentPackageJSONType(
const FunctionCallbackInfo<Value>& args) {
CHECK_GE(args.Length(), 1);
CHECK(args[0]->IsString());

Realm* realm = Realm::GetCurrent(args);
BufferValue path_value(realm->isolate(), args[0]);
// Check if the path has a trailing slash. If so, add it after
// ToNamespacedPath() as it will be deleted by ToNamespacedPath()
bool slashCheck = path_value.ToStringView().ends_with(kPathSeparator);

ToNamespacedPath(realm->env(), &path_value);

std::string path_value_str = path_value.ToString();
if (slashCheck) {
path_value_str.push_back(kPathSeparator);
}

auto package_json =
TraverseParent(realm, std::filesystem::path(path_value_str));
const FunctionCallbackInfo<Value>& args
) {
auto package_json = GetNearestParentPackageJSON(args);

if (package_json == nullptr) {
return;
}

Local<Value> value =
ToV8Value(realm->context(), package_json->type).ToLocalChecked();
Local<Value> value = ToV8Value(realm->context(), package_json->type).ToLocalChecked();

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

Expand Down Expand Up @@ -497,6 +489,7 @@ void BindingData::CreatePerIsolateProperties(IsolateData* isolate_data,
SetMethod(isolate, target, "getPackageScopeConfig", GetPackageScopeConfig);
SetMethod(isolate, target, "enableCompileCache", EnableCompileCache);
SetMethod(isolate, target, "getCompileCacheDir", GetCompileCacheDir);
SetMethod(isolate, target, "findNearestPackageJSON", FindNearestParentPackageJSON);
SetMethod(isolate, target, "flushCompileCache", FlushCompileCache);
}

Expand Down
1 change: 1 addition & 0 deletions typings/internalBinding/modules.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@ export interface ModulesBinding {
getNearestParentPackageJSONType(path: string): PackageConfig['type']
getPackageScopeConfig(path: string): SerializedPackageConfig | undefined
getPackageJSONScripts(): string | undefined
findNearestPackageJSON(origin: URL['pathname']): URL['pathname'] | undefined
}