summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/tests/unit_node/fs_test.ts39
-rw-r--r--ext/node/lib.rs17
-rw-r--r--ext/node/ops/fs.rs26
-rw-r--r--ext/node/ops/mod.rs1
-rw-r--r--ext/node/polyfills/_fs/_fs_exists.ts9
-rw-r--r--runtime/permissions/mod.rs8
-rw-r--r--runtime/snapshot.rs6
7 files changed, 93 insertions, 13 deletions
diff --git a/cli/tests/unit_node/fs_test.ts b/cli/tests/unit_node/fs_test.ts
index 310113233..d9fe3af76 100644
--- a/cli/tests/unit_node/fs_test.ts
+++ b/cli/tests/unit_node/fs_test.ts
@@ -3,7 +3,8 @@
import { assert, assertThrows } from "../../../test_util/std/assert/mod.ts";
import { join } from "node:path";
import { tmpdir } from "node:os";
-import { mkdtempSync, readFileSync, writeFileSync } from "node:fs";
+import { existsSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs";
+import { pathToAbsoluteFileUrl } from "../unit/test_util.ts";
Deno.test(
"[node/fs writeFileSync] write file without option",
@@ -43,3 +44,39 @@ Deno.test(
);
},
);
+
+Deno.test(
+ "[node/fs existsSync] path",
+ { permissions: { read: true } },
+ () => {
+ assert(existsSync("cli/tests/testdata/assets/fixture.json"));
+ },
+);
+
+Deno.test(
+ "[node/fs existsSync] url",
+ { permissions: { read: true } },
+ () => {
+ assert(existsSync(
+ pathToAbsoluteFileUrl("cli/tests/testdata/assets/fixture.json"),
+ ));
+ },
+);
+
+Deno.test(
+ "[node/fs existsSync] no permission",
+ { permissions: { read: false } },
+ () => {
+ assertThrows(() => {
+ existsSync("cli/tests/testdata/assets/fixture.json");
+ }, Deno.errors.PermissionDenied);
+ },
+);
+
+Deno.test(
+ "[node/fs existsSync] not exists",
+ { permissions: { read: true } },
+ () => {
+ assert(!existsSync("bad_filename"));
+ },
+);
diff --git a/ext/node/lib.rs b/ext/node/lib.rs
index 7fa5b893b..547f1d60a 100644
--- a/ext/node/lib.rs
+++ b/ext/node/lib.rs
@@ -50,7 +50,15 @@ pub trait NodePermissions {
url: &Url,
api_name: &str,
) -> Result<(), AnyError>;
- fn check_read(&self, path: &Path) -> Result<(), AnyError>;
+ #[inline(always)]
+ fn check_read(&self, path: &Path) -> Result<(), AnyError> {
+ self.check_read_with_api_name(path, None)
+ }
+ fn check_read_with_api_name(
+ &self,
+ path: &Path,
+ api_name: Option<&str>,
+ ) -> Result<(), AnyError>;
fn check_sys(&self, kind: &str, api_name: &str) -> Result<(), AnyError>;
}
@@ -64,7 +72,11 @@ impl NodePermissions for AllowAllNodePermissions {
) -> Result<(), AnyError> {
Ok(())
}
- fn check_read(&self, _path: &Path) -> Result<(), AnyError> {
+ fn check_read_with_api_name(
+ &self,
+ _path: &Path,
+ _api_name: Option<&str>,
+ ) -> Result<(), AnyError> {
Ok(())
}
fn check_sys(&self, _kind: &str, _api_name: &str) -> Result<(), AnyError> {
@@ -227,6 +239,7 @@ deno_core::extension!(deno_node,
ops::crypto::x509::op_node_x509_get_valid_to,
ops::crypto::x509::op_node_x509_get_serial_number,
ops::crypto::x509::op_node_x509_key_usage,
+ ops::fs::op_node_fs_exists_sync<P>,
ops::winerror::op_node_sys_to_uv_error,
ops::v8::op_v8_cached_data_version_tag,
ops::v8::op_v8_get_heap_statistics,
diff --git a/ext/node/ops/fs.rs b/ext/node/ops/fs.rs
new file mode 100644
index 000000000..b21652634
--- /dev/null
+++ b/ext/node/ops/fs.rs
@@ -0,0 +1,26 @@
+// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
+
+use std::path::PathBuf;
+
+use deno_core::error::AnyError;
+use deno_core::op2;
+use deno_core::OpState;
+use deno_fs::FileSystemRc;
+
+use crate::NodePermissions;
+
+#[op2(fast)]
+pub fn op_node_fs_exists_sync<P>(
+ state: &mut OpState,
+ #[string] path: String,
+) -> Result<bool, AnyError>
+where
+ P: NodePermissions + 'static,
+{
+ let path = PathBuf::from(path);
+ state
+ .borrow_mut::<P>()
+ .check_read_with_api_name(&path, Some("node:fs.existsSync()"))?;
+ let fs = state.borrow::<FileSystemRc>();
+ Ok(fs.lstat_sync(&path).is_ok())
+}
diff --git a/ext/node/ops/mod.rs b/ext/node/ops/mod.rs
index d1bb4b7f4..ec4324da3 100644
--- a/ext/node/ops/mod.rs
+++ b/ext/node/ops/mod.rs
@@ -1,6 +1,7 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
pub mod crypto;
+pub mod fs;
pub mod http;
pub mod http2;
pub mod idna;
diff --git a/ext/node/polyfills/_fs/_fs_exists.ts b/ext/node/polyfills/_fs/_fs_exists.ts
index 9c8458b58..db41aedec 100644
--- a/ext/node/polyfills/_fs/_fs_exists.ts
+++ b/ext/node/polyfills/_fs/_fs_exists.ts
@@ -2,7 +2,7 @@
// TODO(petamoriken): enable prefer-primordials for node polyfills
// deno-lint-ignore-file prefer-primordials
-
+const core = globalThis.__bootstrap.core;
import { pathFromURL } from "ext:deno_web/00_infra.js";
type ExistsCallback = (exists: boolean) => void;
@@ -35,10 +35,5 @@ Object.defineProperty(exists, kCustomPromisifiedSymbol, {
*/
export function existsSync(path: string | URL): boolean {
path = path instanceof URL ? pathFromURL(path) : path;
- try {
- Deno.lstatSync(path);
- return true;
- } catch (_err) {
- return false;
- }
+ return core.ops.op_node_fs_exists_sync(path);
}
diff --git a/runtime/permissions/mod.rs b/runtime/permissions/mod.rs
index 75d4af1c7..7677b5c36 100644
--- a/runtime/permissions/mod.rs
+++ b/runtime/permissions/mod.rs
@@ -1376,8 +1376,12 @@ impl deno_node::NodePermissions for PermissionsContainer {
}
#[inline(always)]
- fn check_read(&self, path: &Path) -> Result<(), AnyError> {
- self.0.lock().read.check(path, None)
+ fn check_read_with_api_name(
+ &self,
+ path: &Path,
+ api_name: Option<&str>,
+ ) -> Result<(), AnyError> {
+ self.0.lock().read.check(path, api_name)
}
fn check_sys(&self, kind: &str, api_name: &str) -> Result<(), AnyError> {
diff --git a/runtime/snapshot.rs b/runtime/snapshot.rs
index f7642573e..a0f0665b4 100644
--- a/runtime/snapshot.rs
+++ b/runtime/snapshot.rs
@@ -76,7 +76,11 @@ impl deno_node::NodePermissions for Permissions {
) -> Result<(), deno_core::error::AnyError> {
unreachable!("snapshotting!")
}
- fn check_read(&self, _p: &Path) -> Result<(), deno_core::error::AnyError> {
+ fn check_read_with_api_name(
+ &self,
+ _p: &Path,
+ _api_name: Option<&str>,
+ ) -> Result<(), deno_core::error::AnyError> {
unreachable!("snapshotting!")
}
fn check_sys(