@@ -2327,6 +2327,84 @@ static void WriteString(const FunctionCallbackInfo<Value>& args) {
23272327 }
23282328}
23292329
2330+ static void WriteFileUtf8 (const FunctionCallbackInfo<Value>& args) {
2331+ // Fast C++ path for fs.writeFileSync(path, data) with utf8 encoding
2332+ // (file, data, options.flag, options.mode)
2333+
2334+ Environment* env = Environment::GetCurrent (args);
2335+ auto isolate = env->isolate ();
2336+
2337+ CHECK_EQ (args.Length (), 4 );
2338+
2339+ BufferValue value (isolate, args[1 ]);
2340+ CHECK_NOT_NULL (*value);
2341+
2342+ CHECK (args[2 ]->IsInt32 ());
2343+ const int flags = args[2 ].As <Int32>()->Value ();
2344+
2345+ CHECK (args[3 ]->IsInt32 ());
2346+ const int mode = args[3 ].As <Int32>()->Value ();
2347+
2348+ uv_file file;
2349+
2350+ bool is_fd = args[0 ]->IsInt32 ();
2351+
2352+ // Check for file descriptor
2353+ if (is_fd) {
2354+ file = args[0 ].As <Int32>()->Value ();
2355+ } else {
2356+ BufferValue path (isolate, args[0 ]);
2357+ CHECK_NOT_NULL (*path);
2358+ if (CheckOpenPermissions (env, path, flags).IsNothing ()) return ;
2359+
2360+ FSReqWrapSync req_open (" open" , *path);
2361+
2362+ FS_SYNC_TRACE_BEGIN (open);
2363+ file =
2364+ SyncCallAndThrowOnError (env, &req_open, uv_fs_open, *path, flags, mode);
2365+ FS_SYNC_TRACE_END (open);
2366+
2367+ if (is_uv_error (file)) {
2368+ return ;
2369+ }
2370+ }
2371+
2372+ int bytesWritten = 0 ;
2373+ uint32_t offset = 0 ;
2374+
2375+ const size_t length = value.length ();
2376+ uv_buf_t uvbuf = uv_buf_init (value.out (), length);
2377+
2378+ FS_SYNC_TRACE_BEGIN (write);
2379+ while (offset < length) {
2380+ FSReqWrapSync req_write (" write" );
2381+ bytesWritten = SyncCallAndThrowOnError (
2382+ env, &req_write, uv_fs_write, file, &uvbuf, 1 , -1 );
2383+
2384+ // Write errored out
2385+ if (bytesWritten < 0 ) {
2386+ break ;
2387+ }
2388+
2389+ offset += bytesWritten;
2390+ DCHECK_LE (offset, length);
2391+ uvbuf.base += bytesWritten;
2392+ uvbuf.len -= bytesWritten;
2393+ }
2394+ FS_SYNC_TRACE_END (write);
2395+
2396+ if (!is_fd) {
2397+ FSReqWrapSync req_close (" close" );
2398+
2399+ FS_SYNC_TRACE_BEGIN (close);
2400+ int result = SyncCallAndThrowOnError (env, &req_close, uv_fs_close, file);
2401+ FS_SYNC_TRACE_END (close);
2402+
2403+ if (is_uv_error (result)) {
2404+ return ;
2405+ }
2406+ }
2407+ }
23302408
23312409/*
23322410 * Wrapper for read(2).
@@ -3169,6 +3247,7 @@ static void CreatePerIsolateProperties(IsolateData* isolate_data,
31693247 SetMethod (isolate, target, " writeBuffer" , WriteBuffer);
31703248 SetMethod (isolate, target, " writeBuffers" , WriteBuffers);
31713249 SetMethod (isolate, target, " writeString" , WriteString);
3250+ SetMethod (isolate, target, " writeFileUtf8" , WriteFileUtf8);
31723251 SetMethod (isolate, target, " realpath" , RealPath);
31733252 SetMethod (isolate, target, " copyFile" , CopyFile);
31743253
@@ -3289,6 +3368,7 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
32893368 registry->Register (WriteBuffer);
32903369 registry->Register (WriteBuffers);
32913370 registry->Register (WriteString);
3371+ registry->Register (WriteFileUtf8);
32923372 registry->Register (RealPath);
32933373 registry->Register (CopyFile);
32943374
0 commit comments