diff --git a/benchmark/fs/bench-linkSync.js b/benchmark/fs/bench-linkSync.js new file mode 100644 index 00000000000000..7c3ef29291913e --- /dev/null +++ b/benchmark/fs/bench-linkSync.js @@ -0,0 +1,50 @@ +'use strict'; + +const common = require('../common'); +const fs = require('fs'); +const assert = require('assert'); +const tmpdir = require('../../test/common/tmpdir'); + +tmpdir.refresh(); +const tmpfile = tmpdir.resolve(`.bench-file-data-${Date.now()}`); +fs.writeFileSync(tmpfile, 'bench-file', 'utf-8'); + +const bench = common.createBenchmark(main, { + type: ['valid', 'invalid'], + n: [1e3], +}); + +function main({ n, type }) { + switch (type) { + case 'valid': { + bench.start(); + for (let i = 0; i < n; i++) { + fs.linkSync(tmpfile, tmpdir.resolve(`.valid-${i}`), 'file'); + } + bench.end(n); + + break; + } + + case 'invalid': { + let hasError = false; + bench.start(); + for (let i = 0; i < n; i++) { + try { + fs.linkSync( + tmpdir.resolve(`.non-existing-file-for-linkSync-${i}`), + __filename, + 'file', + ); + } catch { + hasError = true; + } + } + bench.end(n); + assert(hasError); + break; + } + default: + new Error('Invalid type'); + } +} diff --git a/lib/fs.js b/lib/fs.js index dc733d3ce66b86..16a61253dc7311 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -1847,12 +1847,10 @@ function linkSync(existingPath, newPath) { existingPath = getValidatedPath(existingPath, 'existingPath'); newPath = getValidatedPath(newPath, 'newPath'); - const ctx = { path: existingPath, dest: newPath }; - const result = binding.link(pathModule.toNamespacedPath(existingPath), - pathModule.toNamespacedPath(newPath), - undefined, ctx); - handleErrorFromBinding(ctx); - return result; + binding.link( + pathModule.toNamespacedPath(existingPath), + pathModule.toNamespacedPath(newPath), + ); } /** diff --git a/src/node_file.cc b/src/node_file.cc index 926fb1e65b9ae9..b98a3eac111b31 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -1342,7 +1342,7 @@ static void Link(const FunctionCallbackInfo& args) { Isolate* isolate = env->isolate(); const int argc = args.Length(); - CHECK_GE(argc, 3); + CHECK_GE(argc, 2); BufferValue src(isolate, args[0]); CHECK_NOT_NULL(*src); @@ -1360,8 +1360,8 @@ static void Link(const FunctionCallbackInfo& args) { THROW_IF_INSUFFICIENT_PERMISSIONS( env, permission::PermissionScope::kFileSystemWrite, dest_view); - FSReqBase* req_wrap_async = GetReqWrap(args, 2); - if (req_wrap_async != nullptr) { // link(src, dest, req) + if (argc > 2) { // link(src, dest, req) + FSReqBase* req_wrap_async = GetReqWrap(args, 2); FS_ASYNC_TRACE_BEGIN2(UV_FS_LINK, req_wrap_async, "src", @@ -1371,11 +1371,9 @@ static void Link(const FunctionCallbackInfo& args) { AsyncDestCall(env, req_wrap_async, args, "link", *dest, dest.length(), UTF8, AfterNoArgs, uv_fs_link, *src, *dest); } else { // link(src, dest) - CHECK_EQ(argc, 4); - FSReqWrapSync req_wrap_sync; + FSReqWrapSync req_wrap_sync("link", *src, *dest); FS_SYNC_TRACE_BEGIN(link); - SyncCall(env, args[3], &req_wrap_sync, "link", - uv_fs_link, *src, *dest); + SyncCallAndThrowOnError(env, &req_wrap_sync, uv_fs_link, *src, *dest); FS_SYNC_TRACE_END(link); } } diff --git a/typings/internalBinding/fs.d.ts b/typings/internalBinding/fs.d.ts index 0f5c29a13025b5..23592809f2c570 100644 --- a/typings/internalBinding/fs.d.ts +++ b/typings/internalBinding/fs.d.ts @@ -121,6 +121,7 @@ declare namespace InternalFSBinding { function link(existingPath: string, newPath: string, req: FSReqCallback): void; function link(existingPath: string, newPath: string, req: undefined, ctx: FSSyncContext): void; function link(existingPath: string, newPath: string, usePromises: typeof kUsePromises): Promise; + function link(existingPath: string, newPath: string): void; function lstat(path: StringOrBuffer, useBigint: boolean, req: FSReqCallback): void; function lstat(path: StringOrBuffer, useBigint: true, req: FSReqCallback): void;