@@ -257,7 +257,8 @@ CompileCacheEntry* CompileCacheHandler::GetOrInsert(Local<String> code,
257257 // If the portable cache is enabled and it seems possible to compute the
258258 // relative position from an absolute path, we use the relative position
259259 // in the cache key.
260- if (portable_ == EnableOption::PORTABLE && IsAbsoluteFilePath (file_path)) {
260+ if (HasOption (portable_, EnableOption::PORTABLE ) &&
261+ IsAbsoluteFilePath (file_path)) {
261262 // Normalize the path to ensure it is consistent.
262263 std::string normalized_file_path = NormalizeFileURLOrPath (env, file_path);
263264 if (normalized_file_path.empty ()) {
@@ -332,6 +333,10 @@ void CompileCacheHandler::MaybeSaveImpl(CompileCacheEntry* entry,
332333 Debug (" keeping the in-memory entry\n " );
333334 return ;
334335 }
336+ if (read_only_) {
337+ Debug (" read-only, not serializing\n " );
338+ return ;
339+ }
335340 Debug (" %s the in-memory entry\n " ,
336341 entry->cache == nullptr ? " initializing" : " refreshing" );
337342
@@ -356,6 +361,9 @@ void CompileCacheHandler::MaybeSave(CompileCacheEntry* entry,
356361
357362void CompileCacheHandler::MaybeSave (CompileCacheEntry* entry,
358363 std::string_view transpiled) {
364+ if (read_only_) {
365+ return ;
366+ }
359367 CHECK (entry->type == CachedCodeType::kStrippedTypeScript );
360368 Debug (" [compile cache] saving transpilation cache for %s %s\n " ,
361369 entry->type_name (),
@@ -388,6 +396,10 @@ void CompileCacheHandler::MaybeSave(CompileCacheEntry* entry,
388396 */
389397void CompileCacheHandler::Persist () {
390398 DCHECK (!compile_cache_dir_.empty ());
399+ if (read_only_) {
400+ Debug (" [compile cache] read-only, skipping persistence\n " );
401+ return ;
402+ }
391403
392404 // TODO(joyeecheung): do this using a separate event loop to utilize the
393405 // libuv thread pool and do the file system operations concurrently.
@@ -554,10 +566,11 @@ CompileCacheEnableResult CompileCacheHandler::Enable(Environment* env,
554566 cache_tag,
555567 cache_dir_with_tag);
556568
557- if (!env->permission ()->is_granted (
558- env,
559- permission::PermissionScope::kFileSystemWrite ,
560- cache_dir_with_tag)) [[unlikely]] {
569+ const bool read_only = HasOption (option, EnableOption::READ_ONLY );
570+ if (!read_only && !env->permission ()->is_granted (
571+ env,
572+ permission::PermissionScope::kFileSystemWrite ,
573+ cache_dir_with_tag)) [[unlikely]] {
561574 result.message = " Skipping compile cache because write permission for " +
562575 cache_dir_with_tag + " is not granted" ;
563576 result.status = CompileCacheEnableStatus::FAILED ;
@@ -574,25 +587,46 @@ CompileCacheEnableResult CompileCacheHandler::Enable(Environment* env,
574587 return result;
575588 }
576589
577- fs::FSReqWrapSync req_wrap;
578- int err = fs::MKDirpSync (
579- nullptr , &(req_wrap.req ), cache_dir_with_tag, 0777 , nullptr );
580- if (is_debug_) {
581- Debug (" [compile cache] creating cache directory %s...%s\n " ,
590+ if (read_only) {
591+ // A read-only cache is used as found and never created: without the
592+ // directory there is nothing to read.
593+ uv_fs_t stat_req;
594+ int err =
595+ uv_fs_stat (nullptr , &stat_req, cache_dir_with_tag.c_str (), nullptr );
596+ // libuv normalizes st_mode across platforms; MSVC has no S_ISDIR macro.
597+ bool is_dir = err == 0 && (stat_req.statbuf .st_mode & S_IFMT ) == S_IFDIR ;
598+ uv_fs_req_cleanup (&stat_req);
599+ Debug (" [compile cache] read-only cache directory %s...%s\n " ,
582600 cache_dir_with_tag,
583- err < 0 ? uv_strerror (err) : " success" );
584- }
585- if (err != 0 && err != UV_EEXIST ) {
586- result.message =
587- " Cannot create cache directory: " + std::string (uv_strerror (err));
588- result.status = CompileCacheEnableStatus::FAILED ;
589- return result;
601+ is_dir ? " found" : " not found" );
602+ if (!is_dir) {
603+ result.message =
604+ " Cache directory does not exist (read-only): " + cache_dir_with_tag;
605+ result.status = CompileCacheEnableStatus::FAILED ;
606+ return result;
607+ }
608+ } else {
609+ fs::FSReqWrapSync req_wrap;
610+ int err = fs::MKDirpSync (
611+ nullptr , &(req_wrap.req ), cache_dir_with_tag, 0777 , nullptr );
612+ if (is_debug_) {
613+ Debug (" [compile cache] creating cache directory %s...%s\n " ,
614+ cache_dir_with_tag,
615+ err < 0 ? uv_strerror (err) : " success" );
616+ }
617+ if (err != 0 && err != UV_EEXIST ) {
618+ result.message =
619+ " Cannot create cache directory: " + std::string (uv_strerror (err));
620+ result.status = CompileCacheEnableStatus::FAILED ;
621+ return result;
622+ }
590623 }
591624
592625 result.cache_directory = absolute_cache_dir_base;
593626 compile_cache_dir_ = cache_dir_with_tag;
594627 portable_ = option;
595- if (option == EnableOption::PORTABLE ) {
628+ read_only_ = read_only;
629+ if (HasOption (option, EnableOption::PORTABLE )) {
596630 normalized_compile_cache_dir_ =
597631 NormalizeFileURLOrPath (env, compile_cache_dir_);
598632 }
0 commit comments