Skip to content

Commit 0adc538

Browse files
committed
Fix Luau require from chunks loaded by path
Fixes #735
1 parent 9e63bcf commit 0adc538

2 files changed

Lines changed: 35 additions & 12 deletions

File tree

‎src/luau/require/fs.rs‎

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -137,20 +137,20 @@ impl Require for FsRequirer {
137137
return Ok(());
138138
}
139139

140-
if chunk_path.is_absolute() {
141-
let resolved_path = Self::resolve_module(&chunk_path)?;
142-
self.abs_path = chunk_path.clone();
143-
self.rel_path = chunk_path;
144-
self.resolved_path = resolved_path;
140+
let abs_path = if chunk_path.is_absolute() {
141+
chunk_path.clone()
145142
} else {
146-
// Relative path
147143
let cwd = env::current_dir().map_err(|_| NavigateError::NotFound)?;
148-
let abs_path = Self::normalize_path(&cwd.join(&chunk_path));
149-
let resolved_path = Self::resolve_module(&abs_path)?;
150-
self.abs_path = abs_path;
151-
self.rel_path = chunk_path;
152-
self.resolved_path = resolved_path;
153-
}
144+
Self::normalize_path(&cwd.join(&chunk_path))
145+
};
146+
// Chunks loaded by path include the file extension, unlike module names.
147+
let resolved_path = match Self::resolve_module(&abs_path) {
148+
Err(NavigateError::NotFound) if abs_path.is_file() => Some(abs_path.clone()),
149+
result => result?,
150+
};
151+
self.abs_path = abs_path;
152+
self.rel_path = chunk_path;
153+
self.resolved_path = resolved_path;
154154

155155
Ok(())
156156
}

‎tests/luau/require.rs‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
use std::fs;
12
use std::io::Result as IoResult;
3+
use std::path::Path;
24
use std::result::Result as StdResult;
35
use std::sync::Arc;
46

@@ -144,6 +146,27 @@ fn test_require_errors() {
144146
assert_eq!(Arc::strong_count(&alive), 1);
145147
}
146148

149+
#[test]
150+
fn test_require_from_path() -> Result<()> {
151+
let dir = tempfile::tempdir_in(".").unwrap();
152+
// Resetting a required module must not pick an unrelated extensionless file.
153+
fs::write(dir.path().join("dependency"), "return 99").unwrap();
154+
fs::write(
155+
dir.path().join("dependency.luau"),
156+
"if not loaded then loaded = true; return require('@self') end; return 42",
157+
)
158+
.unwrap();
159+
for name in ["main.luau", "main.lua", "init.luau"] {
160+
let path = Path::new(dir.path().file_name().unwrap()).join(name);
161+
fs::write(&path, "return require('./dependency')").unwrap();
162+
for path in [path.clone(), path.canonicalize().unwrap()] {
163+
let lua = Lua::new();
164+
assert_eq!(lua.load(path.as_path()).eval::<i32>()?, 42);
165+
}
166+
}
167+
Ok(())
168+
}
169+
147170
#[test]
148171
fn test_require_without_config() {
149172
let lua = Lua::new();

0 commit comments

Comments
 (0)