From 1d2c0d424808080632b5f20174a3a6f2dfcd48d4 Mon Sep 17 00:00:00 2001 From: "Dylan M. Taylor" Date: Wed, 28 Oct 2026 06:09:21 +0000 Subject: [PATCH] Refactor script for strict Clippy checks --- crates/script/src/prelude.js | 11 ++++++++--- crates/script/src/socket.rs | 2 +- crates/script/src/tests.rs | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 4 deletions(-) diff --git a/crates/script/src/prelude.js b/crates/script/src/prelude.js index ce64e221b..f012ce128 100644 --- a/crates/script/src/prelude.js +++ b/crates/script/src/prelude.js @@ -189,7 +189,12 @@ BridgeTalk.pump = function () { return false; }; // ------------------------------------------------------------------ File / Folder -function __join(a, b) { return a.replace(/[\/\\]+$/, "") + "/" + b; } +function __trimPathSeparators(path) { + var end = path.length; + while (end > 0 && (path.charAt(end - 1) === "/" || path.charAt(end - 1) === "\\")) end--; + return path.slice(0, end); +} +function __join(a, b) { return __trimPathSeparators(a) + "/" + b; } function File(path) { if (!(this instanceof File)) return new File(path); @@ -292,9 +297,9 @@ Folder.prototype = { get fsName() { return this.__path; }, get fullName() { return this.__path; }, get absoluteURI() { return this.__path; }, - get name() { return this.__path.replace(/[\/\\]+$/, "").split(/[\/\\]/).pop(); }, + get name() { return __trimPathSeparators(this.__path).split(/[\/\\]/).pop(); }, get displayName() { return this.name; }, - get path() { var p = this.__path.replace(/[\/\\]+$/, "").split(/[\/\\]/); p.pop(); return p.join("/"); }, + get path() { var p = __trimPathSeparators(this.__path).split(/[\/\\]/); p.pop(); return p.join("/"); }, get parent() { return new Folder(this.path); }, get exists() { return JSON.parse(__file("isDir", this.__path)) === true; }, toString: function () { return this.__path; }, diff --git a/crates/script/src/socket.rs b/crates/script/src/socket.rs index 6b2976dc1..4103f12c1 100644 --- a/crates/script/src/socket.rs +++ b/crates/script/src/socket.rs @@ -55,7 +55,7 @@ mod imp { use std::sync::{Arc, Mutex}; use std::time::{Duration, Instant}; - use super::*; + use super::{J, err, json}; enum Sock { Stream { s: TcpStream, buf: Vec, eof: bool }, diff --git a/crates/script/src/tests.rs b/crates/script/src/tests.rs index 8b7973c5d..c0411585b 100644 --- a/crates/script/src/tests.rs +++ b/crates/script/src/tests.rs @@ -456,6 +456,38 @@ fn layers_items_and_markers() { ); } +#[test] +fn folder_paths_trim_trailing_separators() { + let mut s = session(); + let o = ok( + &mut s, + r#" + var paths = ['', '/', '///', 'a/b/', 'a\\b\\/', 'a/b', 'a/\n']; + var result = paths.map(function (path) { + var folder = new Folder(path); + return [folder.name, folder.path, __join(path, 'child')]; + }); + // A long run followed by a non-separator used to cause quadratic regex backtracking. + var longPath = Array(20001).join('/') + 'x'; + result.push([new Folder(longPath).name, new Folder(longPath).path.length, __join(longPath, 'child').length]); + result + "#, + ); + assert_eq!( + o.result, + json!([ + ["", "", "/child"], + ["", "", "/child"], + ["", "", "/child"], + ["b", "a", "a/b/child"], + ["b", "a", "a\\b/child"], + ["b", "a", "a/b/child"], + ["\n", "a", "a/\n/child"], + ["x", 19999, 20007] + ]) + ); +} + #[test] fn security_gate_for_files() { let dir = std::env::temp_dir().join(format!("ec-script-gate-{}", std::process::id()));