Skip to content

Commit 390654e

Browse files
anonrigaduh95
authored andcommitted
src: fix internalModuleStat v8 fast path
PR-URL: #58054 Backport-PR-URL: #59065 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Robert Nagy <ronagy@icloud.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
1 parent 2fc8989 commit 390654e

File tree

8 files changed

+36
-25
lines changed

8 files changed

+36
-25
lines changed

lib/fs.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1448,7 +1448,7 @@ function handleDirents({ result, currentPath, context }) {
14481448
const dirent = getDirent(currentPath, names[i], types[i]);
14491449
ArrayPrototypePush(context.readdirResults, dirent);
14501450

1451-
if (dirent.isDirectory() || binding.internalModuleStat(binding, fullPath) === 1) {
1451+
if (dirent.isDirectory() || binding.internalModuleStat(fullPath) === 1) {
14521452
ArrayPrototypePush(context.pathsQueue, fullPath);
14531453
}
14541454
}
@@ -1458,7 +1458,7 @@ function handleFilePaths({ result, currentPath, context }) {
14581458
for (let i = 0; i < result.length; i++) {
14591459
const resultPath = pathModule.join(currentPath, result[i]);
14601460
const relativeResultPath = pathModule.relative(context.basePath, resultPath);
1461-
const stat = binding.internalModuleStat(binding, resultPath);
1461+
const stat = binding.internalModuleStat(resultPath);
14621462
ArrayPrototypePush(context.readdirResults, relativeResultPath);
14631463

14641464
if (stat === 1) {

lib/internal/fs/promises.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -915,7 +915,7 @@ async function readdirRecursive(originalPath, options) {
915915
const { 0: path, 1: readdir } = ArrayPrototypePop(queue);
916916
for (const ent of readdir) {
917917
const direntPath = pathModule.join(path, ent);
918-
const stat = binding.internalModuleStat(binding, direntPath);
918+
const stat = binding.internalModuleStat(direntPath);
919919
ArrayPrototypePush(
920920
result,
921921
pathModule.relative(originalPath, direntPath),

lib/internal/modules/cjs/loader.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -255,9 +255,9 @@ function stat(filename) {
255255
const result = statCache.get(filename);
256256
if (result !== undefined) { return result; }
257257
}
258-
const result = internalFsBinding.internalModuleStat(internalFsBinding, filename);
258+
const result = internalFsBinding.internalModuleStat(filename);
259259
if (statCache !== null && result >= 0) {
260-
// Only set cache when `internalModuleStat(internalFsBinding, filename)` succeeds.
260+
// Only set cache when `internalModuleStat(filename)` succeeds.
261261
statCache.set(filename, result);
262262
}
263263
return result;

lib/internal/modules/esm/resolve.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,6 @@ function finalizeResolution(resolved, base, preserveSymlinks) {
248248
}
249249

250250
const stats = internalFsBinding.internalModuleStat(
251-
internalFsBinding,
252251
StringPrototypeEndsWith(internalFsBinding, path, '/') ? StringPrototypeSlice(path, -1) : path,
253252
);
254253

lib/internal/modules/package_json_reader.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,6 @@ function getPackageJSONURL(specifier, base) {
235235
let lastPath;
236236
do {
237237
const stat = internalFsBinding.internalModuleStat(
238-
internalFsBinding,
239238
StringPrototypeSlice(packageJSONPath, 0, packageJSONPath.length - 13),
240239
);
241240
// Check for !stat.isDirectory()

src/node_external_reference.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,8 @@ using CFunctionCallback = void (*)(v8::Local<v8::Value> unused,
2020
using CFunctionCallbackReturnDouble =
2121
double (*)(v8::Local<v8::Object> unused, v8::Local<v8::Object> receiver);
2222
using CFunctionCallbackReturnInt32 =
23-
int32_t (*)(v8::Local<v8::Object> unused,
24-
v8::Local<v8::Object> receiver,
25-
const v8::FastOneByteString& input,
23+
int32_t (*)(v8::Local<v8::Value> receiver,
24+
v8::Local<v8::Value> input,
2625
// NOLINTNEXTLINE(runtime/references) This is V8 api.
2726
v8::FastApiCallbackOptions& options);
2827
using CFunctionCallbackValueReturnDouble =

src/node_file.cc

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "aliased_buffer-inl.h"
2424
#include "memory_tracker-inl.h"
2525
#include "node_buffer.h"
26+
#include "node_debug.h"
2627
#include "node_errors.h"
2728
#include "node_external_reference.h"
2829
#include "node_file-inl.h"
@@ -60,8 +61,6 @@ using v8::BigInt;
6061
using v8::Context;
6162
using v8::EscapableHandleScope;
6263
using v8::FastApiCallbackOptions;
63-
using v8::FastOneByteString;
64-
using v8::Function;
6564
using v8::FunctionCallbackInfo;
6665
using v8::FunctionTemplate;
6766
using v8::HandleScope;
@@ -1051,9 +1050,9 @@ static void ExistsSync(const FunctionCallbackInfo<Value>& args) {
10511050
static void InternalModuleStat(const FunctionCallbackInfo<Value>& args) {
10521051
Environment* env = Environment::GetCurrent(args);
10531052

1054-
CHECK_GE(args.Length(), 2);
1055-
CHECK(args[1]->IsString());
1056-
BufferValue path(env->isolate(), args[1]);
1053+
CHECK_EQ(args.Length(), 1);
1054+
CHECK(args[0]->IsString());
1055+
BufferValue path(env->isolate(), args[0]);
10571056
CHECK_NOT_NULL(*path);
10581057
ToNamespacedPath(env, &path);
10591058

@@ -1069,9 +1068,8 @@ static void InternalModuleStat(const FunctionCallbackInfo<Value>& args) {
10691068
}
10701069

10711070
static int32_t FastInternalModuleStat(
1072-
Local<Object> unused,
1073-
Local<Object> recv,
1074-
const FastOneByteString& input,
1071+
Local<Value> recv,
1072+
Local<Value> input_,
10751073
// NOLINTNEXTLINE(runtime/references) This is V8 api.
10761074
FastApiCallbackOptions& options) {
10771075
// This needs a HandleScope which needs an isolate.
@@ -1081,9 +1079,13 @@ static int32_t FastInternalModuleStat(
10811079
return -1;
10821080
}
10831081

1082+
TRACK_V8_FAST_API_CALL("fs.internalModuleStat");
10841083
HandleScope scope(isolate);
10851084

1086-
auto path = std::filesystem::path(input.data, input.data + input.length);
1085+
CHECK(input_->IsString());
1086+
Utf8Value input(isolate, input_.As<String>());
1087+
1088+
auto path = std::filesystem::path(input.ToStringView());
10871089

10881090
switch (std::filesystem::status(path).type()) {
10891091
case std::filesystem::file_type::directory:

test/parallel/test-permission-fs-internal-module-stat.js

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
// Flags: --expose-internals --permission --allow-fs-read=test/common* --allow-fs-read=tools* --allow-fs-read=test/parallel* --allow-child-process
1+
// Flags: --expose-internals --permission --allow-fs-read=test/common* --allow-fs-read=tools* --allow-fs-read=test/parallel* --allow-child-process --allow-natives-syntax
22
'use strict';
33

44
const common = require('../common');
55
const { isMainThread } = require('worker_threads');
6+
const { strictEqual } = require('assert');
67

78
if (!isMainThread) {
89
common.skip('This test only works on a main thread');
@@ -18,9 +19,20 @@ const fixtures = require('../common/fixtures');
1819
const blockedFile = fixtures.path('permission', 'deny', 'protected-file.md');
1920
const internalFsBinding = internalBinding('fs');
2021

21-
// Run this inside a for loop to trigger the fast API
22-
for (let i = 0; i < 10_000; i++) {
23-
// internalModuleStat does not use permission model.
24-
// doesNotThrow
25-
internalFsBinding.internalModuleStat(internalFsBinding, blockedFile);
22+
strictEqual(internalFsBinding.internalModuleStat(blockedFile), 0);
23+
24+
// Only javascript methods can be optimized through %OptimizeFunctionOnNextCall
25+
// This is why we surround the C++ method we want to optimize with a JS function.
26+
function testFastPaths(file) {
27+
return internalFsBinding.internalModuleStat(file);
28+
}
29+
30+
eval('%PrepareFunctionForOptimization(testFastPaths)');
31+
testFastPaths(blockedFile);
32+
eval('%OptimizeFunctionOnNextCall(testFastPaths)');
33+
strictEqual(testFastPaths(blockedFile), 0);
34+
35+
if (common.isDebug) {
36+
const { getV8FastApiCallCount } = internalBinding('debug');
37+
strictEqual(getV8FastApiCallCount('fs.internalModuleStat'), 1);
2638
}

0 commit comments

Comments
 (0)