Skip to content

Commit 5eda550

Browse files
authored
Merge pull request #273 from FreeMasen/validate-ptr
Validate ptr
2 parents 0bfa058 + e9ea2da commit 5eda550

File tree

4 files changed

+78
-1
lines changed

4 files changed

+78
-1
lines changed

crates/backend/src/ast.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use proc_macro2::{Ident, Span, TokenStream, TokenTree};
22
use quote::ToTokens;
33
use shared;
44
use syn;
5+
use syn::AttrStyle;
56

67
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
78
#[derive(Default)]

crates/cli-support/src/js/js2rust.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
6868
/// passed should be `this.ptr`.
6969
pub fn method(&mut self, method: bool) -> &mut Self {
7070
if method {
71+
self.prelude("if (this.ptr === 0) {
72+
throw new Error('Attempt to use a moved value');
73+
}");
7174
self.rust_arguments.insert(0, "this.ptr".to_string());
7275
}
7376
self
@@ -149,6 +152,9 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
149152
} else {
150153
self.prelude(&format!("\
151154
const ptr{i} = {arg}.ptr;\n\
155+
if (ptr{i} === 0) {{
156+
throw new Error('Attempt to use a moved value');
157+
}}
152158
{arg}.ptr = 0;\n\
153159
", i = i, arg = name));
154160
self.rust_arguments.push(format!("ptr{}", i));
@@ -361,4 +367,4 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
361367
let ts = format!("{} {}({}): {};\n", prefix, self.js_name, ts_args, self.ret_ty);
362368
(js, ts)
363369
}
364-
}
370+
}

tests/all/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,3 +539,4 @@ mod structural;
539539
mod u64;
540540
mod webidl;
541541
mod comments;
542+
mod validate_prt;

tests/all/validate_prt.rs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
use super::project;
2+
3+
#[test]
4+
fn works() {
5+
project()
6+
.file("src/lib.rs", r#"
7+
#![feature(proc_macro, wasm_custom_section, wasm_import_module)]
8+
extern crate wasm_bindgen;
9+
use wasm_bindgen::prelude::*;
10+
#[wasm_bindgen]
11+
pub struct Fruit {
12+
name: String,
13+
}
14+
#[wasm_bindgen]
15+
impl Fruit {
16+
#[wasm_bindgen(method)]
17+
pub fn name(&self) -> String {
18+
self.name.clone()
19+
}
20+
#[wasm_bindgen(constructor)]
21+
pub fn new(name: String) -> Self {
22+
Fruit {
23+
name,
24+
}
25+
}
26+
}
27+
#[wasm_bindgen]
28+
pub fn eat(_fruit: Fruit) { }
29+
"#)
30+
.file("test.js", r#"
31+
import * as wasm from './out';
32+
const targetMessage = 'Attempt to use a moved value';
33+
function assertEq(a, b) {
34+
console.log(a, '?=', b);
35+
if (a === b)
36+
return;
37+
throw new Error('not equal');
38+
}
39+
export function test() {
40+
useMoved();
41+
moveMoved();
42+
}
43+
export function useMoved() {
44+
// create a new struct
45+
let apple = new wasm.Fruit('apple');
46+
// sanity check that this method works
47+
let name = apple.name();
48+
// consume the struct
49+
wasm.eat(apple);
50+
// try and use the moved apple again
51+
try {
52+
let movedName = apple.name();
53+
} catch (e) {
54+
assertEq(e.message, targetMessage);
55+
}
56+
}
57+
export function moveMoved() {
58+
let pear = new wasm.Fruit('pear');
59+
let name = pear.name();
60+
wasm.eat(pear);
61+
try {
62+
wasm.eat(pear);
63+
} catch (e) {
64+
assertEq(e.message, targetMessage);
65+
}
66+
}
67+
"#)
68+
.test();
69+
}

0 commit comments

Comments
 (0)