Skip to content

Commit 6e125d2

Browse files
committed
Fix missing regex errors and fix double space bug
1 parent e71aea5 commit 6e125d2

File tree

15 files changed

+206
-44
lines changed

15 files changed

+206
-44
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ lto = true
116116
opt-level = 3
117117
panic = "abort"
118118
split-debuginfo = "packed"
119-
strip = "symbols"
119+
strip = false # "symbols"
120120
incremental = true
121121
rpath = true
122122

Justfile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ build-lib target="":
1616

1717
build target="":
1818
@echo "Building for target: {{target}}"
19-
{{env_vars}} cargo build -p divvun-runtime-cli --features divvun-runtime/all-mods --release {{ if target != "" { "--target" } else { "" } }} {{ target }}
19+
{{env_vars}} cargo build -p divvun-runtime-cli --features divvun-runtime/all-mods,ffi --release {{ if target != "" { "--target" } else { "" } }} {{ target }}
20+
strip -x -S ./target/{{ if target != "" { target + "/" } else { "" } }}release/divvun-runtime
2021

2122
# Install built binary
2223
install target="": (build target)

bindings/deno/mod.ts

Lines changed: 55 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,38 @@
1-
import * as path from "jsr:@std/path";
1+
const BRAND = Symbol("divvun-runtime")
22

3-
let libPath: string | null = null;
3+
let libPath: string | null = await findLib();
4+
5+
export function getLibPath(): string | null {
6+
return libPath;
7+
}
8+
9+
export async function findLib(): Promise<string | null> {
10+
const name = "divvun-runtime"
11+
let pathEnv
12+
try {
13+
pathEnv = Deno.env.get("PATH") ?? "";
14+
} catch (e) {
15+
pathEnv = "";
16+
}
17+
const paths = pathEnv.split(Deno.build.os === "windows" ? ";" : ":");
18+
19+
const exts = Deno.build.os === "windows"
20+
? (Deno.env.get("PATHEXT")?.split(";") ?? [".EXE", ".CMD", ".BAT"])
21+
: [""];
22+
23+
for (const dir of paths) {
24+
for (const ext of exts) {
25+
const full = `${dir}/${name}${ext}`;
26+
try {
27+
const info = await Deno.stat(full);
28+
if (info.isFile) return full;
29+
} catch {
30+
// ignore ENOENT
31+
}
32+
}
33+
}
34+
return null;
35+
}
436

537
export function setLibPath(newPath: string) {
638
libPath = newPath;
@@ -11,24 +43,11 @@ let dylib: Deno.DynamicLibrary<Record<string, Deno.ForeignFunction>>;
1143
const RustSliceT = { "struct": ["pointer", "usize"] } as const;
1244

1345
function loadDylib() {
14-
let libSuffix = "";
15-
16-
switch (Deno.build.os) {
17-
case "windows":
18-
libSuffix = "dll";
19-
break;
20-
case "darwin":
21-
libSuffix = "dylib";
22-
break;
23-
default:
24-
libSuffix = "so";
25-
break;
46+
if (libPath == null) {
47+
throw new Error("Could not find divvun-runtime library. Please set the path using setLibPath().");
2648
}
2749

28-
const libName = `libdivvun_runtime.${libSuffix}`;
29-
const fullLibPath = libPath ? path.join(libPath, libName) : libName;
30-
31-
dylib = Deno.dlopen(fullLibPath, {
50+
dylib = Deno.dlopen(libPath, {
3251
DRT_Bundle_fromBundle: {
3352
parameters: [RustSliceT, "function"],
3453
result: "pointer",
@@ -93,7 +112,7 @@ export class Bundle {
93112
errCallback.pointer,
94113
) as Deno.PointerValue<Bundle>;
95114

96-
return new Bundle(bundleRawPtr);
115+
return new Bundle(bundleRawPtr, BRAND);
97116
} catch (e) {
98117
throw e;
99118
}
@@ -112,13 +131,16 @@ export class Bundle {
112131
errCallback.pointer,
113132
) as Deno.PointerValue<Bundle>;
114133

115-
return new Bundle(bundleRawPtr);
134+
return new Bundle(bundleRawPtr, BRAND);
116135
} catch (e) {
117136
throw e;
118137
}
119138
}
120139

121-
private constructor(ptr: Deno.PointerValue) {
140+
private constructor(ptr: Deno.PointerValue, brand: symbol) {
141+
if (brand !== BRAND) {
142+
throw new TypeError("Bundle must be constructed via fromPath or fromBundle");
143+
}
122144
this.#ptr = ptr;
123145
}
124146

@@ -145,7 +167,7 @@ export class Bundle {
145167
errCallback.pointer,
146168
) as Deno.PointerValue<PipelineHandle>;
147169

148-
return new PipelineHandle(pipeRawPtr);
170+
return new PipelineHandle(pipeRawPtr, BRAND);
149171
} catch (e) {
150172
throw e;
151173
}
@@ -157,7 +179,11 @@ class PipelineResponse {
157179
#ptr: Deno.PointerValue;
158180
#len: number;
159181

160-
constructor(buf: Uint8Array) {
182+
constructor(buf: Uint8Array, brand: symbol) {
183+
if (brand !== BRAND) {
184+
throw new TypeError("PipelineResponse cannot be constructed directly");
185+
}
186+
161187
this.#buf = buf;
162188

163189
const ptr = Deno.UnsafePointer.of(buf);
@@ -220,7 +246,11 @@ class PipelineResponse {
220246
export class PipelineHandle {
221247
#ptr: Deno.PointerValue;
222248

223-
constructor(ptr: Deno.PointerValue) {
249+
constructor(ptr: Deno.PointerValue, brand: symbol) {
250+
if (brand !== BRAND) {
251+
throw new TypeError("PipelineHandle cannot be constructed directly");
252+
}
253+
224254
this.#ptr = ptr;
225255
}
226256

@@ -244,7 +274,7 @@ export class PipelineHandle {
244274
rsInput,
245275
errCallback.pointer,
246276
) as Uint8Array;
247-
return new PipelineResponse(outputSlice);
277+
return new PipelineResponse(outputSlice, BRAND);
248278
} catch (e) {
249279
throw e;
250280
}

build.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
1010
println!("cargo:rustc-link-lib=icui18n");
1111
} else if target_os == "macos" {
1212
println!("cargo:rustc-link-lib=icucore");
13+
// println!("cargo:rustc-link-arg=-Wl,-export_dynamic");
14+
println!("cargo:rustc-link-arg=-Wl,-all_load");
1315
} else if target_os == "linux" {
1416
println!("cargo:rustc-link-lib=icuuc");
1517
println!("cargo:rustc-link-lib=icuio");

cli/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ license = "GPL-3.0"
99
name = "divvun-runtime"
1010
path = "src/main.rs"
1111

12-
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
12+
[features]
13+
ffi = ["divvun-runtime/ffi"]
1314

1415
[dependencies]
1516
divvun-runtime = { default-features = false, path = ".." }

cli/build.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,24 @@ fn main() {
55
//
66
} else if target_os == "macos" {
77
println!("cargo:rustc-link-lib=icucore");
8+
// println!("cargo:rustc-link-arg=-Wl,-all_load");
9+
// println!("cargo:rustc-link-arg=-Wl,-export_dynamic");
10+
// println!("cargo:rustc-link-arg=-Wl,-exported_symbol,_DRT_Bundle_fromBundle");
11+
// println!("cargo:rustc-link-arg=-Wl,-exported_symbol,_DRT_Bundle_create");
12+
const EXPORT: &[&str] = &[
13+
"_DRT_Bundle_fromBundle",
14+
"_DRT_Bundle_drop",
15+
"_DRT_Bundle_fromPath",
16+
"_DRT_Bundle_create",
17+
"_DRT_PipelineHandle_drop",
18+
"_DRT_Vec_drop",
19+
"_DRT_PipelineHandle_forward",
20+
"_DRT_Bundle_runPipeline",
21+
];
22+
23+
for exp in EXPORT {
24+
println!("cargo:rustc-link-arg=-Wl,-exported_symbol,{exp}");
25+
}
826
} else if target_os == "linux" {
927
println!("cargo:rustc-link-lib=icuuc");
1028
println!("cargo:rustc-link-lib=icuio");

cli/src/cli.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ pub enum Command {
2222
List(ListArgs),
2323
#[command(alias = "play")]
2424
Playground(PlaygroundArgs),
25+
Test(TestArgs),
2526
#[command(flatten)]
2627
Debug(DebugArgs),
2728
}
@@ -108,3 +109,13 @@ pub struct PlaygroundArgs {
108109
/// Path to open in playground. Defaults to current directory.
109110
pub path: Option<PathBuf>,
110111
}
112+
113+
#[derive(Parser, Debug)]
114+
pub struct TestArgs {
115+
/// Test files to run
116+
pub files: Vec<PathBuf>,
117+
118+
/// Arguments to pass to the test script (after --)
119+
#[clap(last = true)]
120+
pub script_args: Vec<String>,
121+
}

cli/src/command/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ pub mod list;
44
pub mod playground;
55
pub mod run;
66
pub mod sync;
7+
pub mod test;
78
pub mod utils;

cli/src/command/playground.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,15 @@ fn find_playground_binary() -> anyhow::Result<PathBuf> {
3232

3333
#[cfg(target_os = "macos")]
3434
{
35-
let app_path = PathBuf::from("/Applications/Divvun Runtime Playground.app/Contents/MacOS/divvun-rt-playground");
35+
let app_path = PathBuf::from(
36+
"/Applications/Divvun Runtime Playground.app/Contents/MacOS/divvun-rt-playground",
37+
);
3638
if app_path.exists() {
3739
return Ok(app_path);
3840
}
3941
}
4042

41-
if let Ok(output) = Command::new("which")
42-
.arg("divvun-rt-playground")
43-
.output()
44-
{
43+
if let Ok(output) = Command::new("which").arg("divvun-rt-playground").output() {
4544
if output.status.success() {
4645
let path_str = String::from_utf8_lossy(&output.stdout).trim().to_string();
4746
if !path_str.is_empty() {

cli/src/command/test.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
use std::io::Write;
2+
use std::process::Command;
3+
4+
use crate::{cli::TestArgs, shell::Shell};
5+
6+
const DENO_MOD_TS: &str = include_str!("../../../bindings/deno/mod.ts");
7+
8+
pub async fn test(_shell: &mut Shell, args: TestArgs) -> anyhow::Result<()> {
9+
let exe_path = std::env::current_exe()?;
10+
11+
let preload_script = format!(
12+
"{}\n\nsetLibPath(\"{}\");\n(globalThis as any)[\"Bundle\"] = Bundle;\n",
13+
DENO_MOD_TS,
14+
exe_path.display()
15+
);
16+
17+
let temp_dir = tempfile::tempdir()?;
18+
let preload_path = temp_dir.path().join("preload.ts");
19+
let mut preload_file = std::fs::File::create(&preload_path)?;
20+
preload_file.write_all(preload_script.as_bytes())?;
21+
preload_file.flush()?;
22+
drop(preload_file);
23+
24+
let mut cmd = Command::new("deno");
25+
cmd.arg("test")
26+
.arg("--allow-ffi")
27+
.arg("--no-check")
28+
.arg("--preload")
29+
.arg(&preload_path);
30+
31+
for file in &args.files {
32+
cmd.arg(file);
33+
}
34+
35+
if !args.script_args.is_empty() {
36+
cmd.arg("--");
37+
for arg in &args.script_args {
38+
cmd.arg(arg);
39+
}
40+
}
41+
42+
let status = cmd.status()?;
43+
44+
if !status.success() {
45+
std::process::exit(status.code().unwrap_or(1));
46+
}
47+
48+
Ok(())
49+
}

0 commit comments

Comments
 (0)