-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathpoint.rs
More file actions
149 lines (124 loc) · 3.36 KB
/
Copy pathpoint.rs
File metadata and controls
149 lines (124 loc) · 3.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
use rong::*;
use rong::{js_class, js_method};
// Define the Point struct with js_class macro
#[js_class(clone)]
#[derive(Debug)]
struct Point {
x: i32,
y: i32,
}
// Implement methods and expose them to JavaScript
#[js_class(rename = "Point2D")]
impl Point {
// Constructor
#[js_method(constructor)]
fn new(x: i32, y: i32) -> Self {
Self { x, y }
}
// Instance properties with getters and setters
#[js_method(getter, enumerable)]
fn x(&self) -> i32 {
self.x
}
#[js_method(setter, rename = "x")]
fn set_x(&mut self, x: i32) {
self.x = x;
}
#[js_method(getter, enumerable)]
fn y(&self) -> i32 {
self.y
}
#[js_method(setter, rename = "y")]
fn set_y(&mut self, y: i32) {
self.y = y;
}
// Regular instance method
#[js_method(rename = "add")]
fn add(&self, other: Point) -> Self {
Self {
x: self.x + other.x,
y: self.y + other.y,
}
}
// Static method
#[js_method]
fn origin() -> Self {
Self { x: 0, y: 0 }
}
// Mutable instance method
#[js_method(rename = "moveBy")]
fn move_by(&mut self, dx: i32, dy: i32) {
self.x += dx;
self.y += dy;
}
#[js_method(gc_mark)]
fn gc_mark_with<F>(&self, _mark_fn: F)
where
F: FnMut(&JSValue),
{
}
}
fn main() {
// Create a JavaScript runtime and context
let rt = RongJS::runtime();
let ctx = rt.context();
// Register our Point class with JavaScript
let _ = ctx.register_class::<Point>();
// Run some JavaScript code that uses our Point class
let result = ctx
.eval::<String>(Source::from_bytes(
r#"
// Create points using constructor
let p1 = new Point2D(10, 20);
let p2 = new Point2D(30, 40);
// Test getters and setters
p1.x = 15;
p1.y = 25;
// Test instance method
let p3 = p1.add(p2);
// Test static method
let origin = Point2D.origin();
// Test mutable method
p1.moveBy(5, 5);
// Return a string representation of our points
`Points:
p1(${p1.x}, ${p1.y}) // Should be (20, 30) after moveBy
p2(${p2.x}, ${p2.y}) // Original (30, 40)
p3(${p3.x}, ${p3.y}) // Sum of original p1 + p2 (45, 65)
origin(${origin.x}, ${origin.y})` // (0, 0)
"#,
))
.unwrap();
println!("{}", result);
// Demonstrate Rust-JavaScript interop
let rust_point = Point::new(100, 200);
let js_point = ctx
.eval::<Point>(Source::from_bytes(
r#"
let p = new Point2D(1, 2);
p.moveBy(10, 20);
p
"#,
))
.unwrap();
println!("\nMixing Rust and JavaScript:");
println!("Rust point: {:?}", rust_point);
println!("JS point: {:?}", js_point);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn point_instances_round_trip_through_methods() {
let runtime = RongJS::runtime();
let ctx = runtime.context();
ctx.register_class::<Point>().expect("register Point");
let point: Point = ctx
.eval(Source::from_bytes(
"new Point2D(2, 3).add(new Point2D(5, 7))",
))
.expect("evaluate Point method");
assert_eq!(point.x, 7);
assert_eq!(point.y, 10);
}
}