@@ -250,7 +250,8 @@ CompileCacheEntry* CompileCacheHandler::GetOrInsert(Local<String> code,
250250 // If the portable cache is enabled and it seems possible to compute the
251251 // relative position from an absolute path, we use the relative position
252252 // in the cache key.
253- if (portable_ == EnableOption::PORTABLE && IsAbsoluteFilePath (file_path)) {
253+ if (HasOption (portable_, EnableOption::PORTABLE ) &&
254+ IsAbsoluteFilePath (file_path)) {
254255 // Normalize the path to ensure it is consistent.
255256 std::string normalized_file_path = NormalizeFileURLOrPath (env, file_path);
256257 if (normalized_file_path.empty ()) {
@@ -325,6 +326,10 @@ void CompileCacheHandler::MaybeSaveImpl(CompileCacheEntry* entry,
325326 Debug (" keeping the in-memory entry\n " );
326327 return ;
327328 }
329+ if (read_only_) {
330+ Debug (" read-only, not serializing\n " );
331+ return ;
332+ }
328333 Debug (" %s the in-memory entry\n " ,
329334 entry->cache == nullptr ? " initializing" : " refreshing" );
330335
@@ -349,6 +354,9 @@ void CompileCacheHandler::MaybeSave(CompileCacheEntry* entry,
349354
350355void CompileCacheHandler::MaybeSave (CompileCacheEntry* entry,
351356 std::string_view transpiled) {
357+ if (read_only_) {
358+ return ;
359+ }
352360 CHECK (entry->type == CachedCodeType::kStrippedTypeScript );
353361 Debug (" [compile cache] saving transpilation cache for %s %s\n " ,
354362 entry->type_name (),
@@ -381,6 +389,10 @@ void CompileCacheHandler::MaybeSave(CompileCacheEntry* entry,
381389 */
382390void CompileCacheHandler::Persist () {
383391 DCHECK (!compile_cache_dir_.empty ());
392+ if (read_only_) {
393+ Debug (" [compile cache] read-only, skipping persistence\n " );
394+ return ;
395+ }
384396
385397 // TODO(joyeecheung): do this using a separate event loop to utilize the
386398 // libuv thread pool and do the file system operations concurrently.
@@ -546,10 +558,11 @@ CompileCacheEnableResult CompileCacheHandler::Enable(Environment* env,
546558 cache_tag,
547559 cache_dir_with_tag);
548560
549- if (!env->permission ()->is_granted (
550- env,
551- permission::PermissionScope::kFileSystemWrite ,
552- cache_dir_with_tag)) [[unlikely]] {
561+ const bool read_only = HasOption (option, EnableOption::READ_ONLY );
562+ if (!read_only && !env->permission ()->is_granted (
563+ env,
564+ permission::PermissionScope::kFileSystemWrite ,
565+ cache_dir_with_tag)) [[unlikely]] {
553566 result.message = " Skipping compile cache because write permission for " +
554567 cache_dir_with_tag + " is not granted" ;
555568 result.status = CompileCacheEnableStatus::FAILED ;
@@ -566,25 +579,46 @@ CompileCacheEnableResult CompileCacheHandler::Enable(Environment* env,
566579 return result;
567580 }
568581
569- fs::FSReqWrapSync req_wrap;
570- int err = fs::MKDirpSync (
571- nullptr , &(req_wrap.req ), cache_dir_with_tag, 0777 , nullptr );
572- if (is_debug_) {
573- Debug (" [compile cache] creating cache directory %s...%s\n " ,
582+ if (read_only) {
583+ // A read-only cache is used as found and never created: without the
584+ // directory there is nothing to read.
585+ uv_fs_t stat_req;
586+ int err =
587+ uv_fs_stat (nullptr , &stat_req, cache_dir_with_tag.c_str (), nullptr );
588+ // libuv normalizes st_mode across platforms; the S_ISDIR macro is not on MSVC.
589+ bool is_dir = err == 0 && (stat_req.statbuf .st_mode & S_IFMT ) == S_IFDIR ;
590+ uv_fs_req_cleanup (&stat_req);
591+ Debug (" [compile cache] read-only cache directory %s...%s\n " ,
574592 cache_dir_with_tag,
575- err < 0 ? uv_strerror (err) : " success" );
576- }
577- if (err != 0 && err != UV_EEXIST ) {
578- result.message =
579- " Cannot create cache directory: " + std::string (uv_strerror (err));
580- result.status = CompileCacheEnableStatus::FAILED ;
581- return result;
593+ is_dir ? " found" : " not found" );
594+ if (!is_dir) {
595+ result.message =
596+ " Cache directory does not exist (read-only): " + cache_dir_with_tag;
597+ result.status = CompileCacheEnableStatus::FAILED ;
598+ return result;
599+ }
600+ } else {
601+ fs::FSReqWrapSync req_wrap;
602+ int err = fs::MKDirpSync (
603+ nullptr , &(req_wrap.req ), cache_dir_with_tag, 0777 , nullptr );
604+ if (is_debug_) {
605+ Debug (" [compile cache] creating cache directory %s...%s\n " ,
606+ cache_dir_with_tag,
607+ err < 0 ? uv_strerror (err) : " success" );
608+ }
609+ if (err != 0 && err != UV_EEXIST ) {
610+ result.message =
611+ " Cannot create cache directory: " + std::string (uv_strerror (err));
612+ result.status = CompileCacheEnableStatus::FAILED ;
613+ return result;
614+ }
582615 }
583616
584617 result.cache_directory = absolute_cache_dir_base;
585618 compile_cache_dir_ = cache_dir_with_tag;
586619 portable_ = option;
587- if (option == EnableOption::PORTABLE ) {
620+ read_only_ = read_only;
621+ if (HasOption (option, EnableOption::PORTABLE )) {
588622 normalized_compile_cache_dir_ =
589623 NormalizeFileURLOrPath (env, compile_cache_dir_);
590624 }
0 commit comments