mirror of
https://github.com/rustwasm/wasm-bindgen.git
synced 2024-12-27 20:15:14 +03:00
dd76707ea1
Awhile back slices switched to being raw views into wasm memory, but this doens't work if we free the underlying memory unconditionally! Moving around a `Vec` is already moving a lot of data, so let's copy it onto the JS heap instead of leaving it in the wasm heap.
492 lines
15 KiB
Rust
492 lines
15 KiB
Rust
use super::project;
|
|
|
|
#[test]
|
|
fn export() {
|
|
project()
|
|
.file("src/lib.rs", r#"
|
|
#![feature(proc_macro, wasm_custom_section)]
|
|
|
|
extern crate wasm_bindgen;
|
|
|
|
use wasm_bindgen::prelude::*;
|
|
|
|
macro_rules! doit {
|
|
($($i:ident)*) => ($(
|
|
#[wasm_bindgen]
|
|
pub fn $i(a: &[$i]) -> Vec<$i> {
|
|
assert_eq!(a.len(), 2);
|
|
assert_eq!(a[0], 1 as $i);
|
|
assert_eq!(a[1], 2 as $i);
|
|
a.to_vec()
|
|
}
|
|
)*)
|
|
}
|
|
|
|
|
|
doit! { i8 u8 i16 u16 i32 u32 f32 f64 }
|
|
"#)
|
|
.file("test.ts", r#"
|
|
import * as assert from "assert";
|
|
import * as wasm from "./out";
|
|
|
|
function assert_arrays_equal(a: any, b: any) {
|
|
console.log(a, b);
|
|
assert.strictEqual(a.length, b.length);
|
|
assert.strictEqual(a.byteLength, b.byteLength);
|
|
for (let i = 0; i < a.length; i++) {
|
|
assert.strictEqual(a[i], b[i]);
|
|
}
|
|
}
|
|
|
|
export function test() {
|
|
const i8 = new Int8Array(2);
|
|
i8[0] = 1;
|
|
i8[1] = 2;
|
|
assert_arrays_equal(wasm.i8(i8), i8);
|
|
const u8 = new Uint8Array(2);
|
|
u8[0] = 1;
|
|
u8[1] = 2;
|
|
assert_arrays_equal(wasm.u8(u8), u8);
|
|
|
|
const i16 = new Int16Array(2);
|
|
i16[0] = 1;
|
|
i16[1] = 2;
|
|
assert_arrays_equal(wasm.i16(i16), i16);
|
|
const u16 = new Uint16Array(2);
|
|
u16[0] = 1;
|
|
u16[1] = 2;
|
|
assert_arrays_equal(wasm.u16(u16), u16);
|
|
|
|
const i32 = new Int32Array(2);
|
|
i32[0] = 1;
|
|
i32[1] = 2;
|
|
wasm.i32(i32);
|
|
assert_arrays_equal(wasm.i32(i32), i32);
|
|
const u32 = new Uint32Array(2);
|
|
u32[0] = 1;
|
|
u32[1] = 2;
|
|
assert_arrays_equal(wasm.u32(u32), u32);
|
|
|
|
const f32 = new Float32Array(2);
|
|
f32[0] = 1;
|
|
f32[1] = 2;
|
|
assert_arrays_equal(wasm.f32(f32), f32);
|
|
const f64 = new Float64Array(2);
|
|
f64[0] = 1;
|
|
f64[1] = 2;
|
|
assert_arrays_equal(wasm.f64(f64), f64);
|
|
}
|
|
"#)
|
|
.test();
|
|
}
|
|
|
|
#[test]
|
|
fn import() {
|
|
project()
|
|
.file("src/lib.rs", r#"
|
|
#![feature(proc_macro, wasm_custom_section, wasm_import_module)]
|
|
|
|
extern crate wasm_bindgen;
|
|
|
|
use wasm_bindgen::prelude::*;
|
|
|
|
macro_rules! doit {
|
|
($(($rust:ident, $js:ident, $i:ident))*) => ($(
|
|
#[wasm_bindgen(module = "./test")]
|
|
extern {
|
|
fn $js(a: &[$i]) -> Vec<$i>;
|
|
}
|
|
|
|
#[wasm_bindgen]
|
|
pub fn $rust(a: &[$i]) -> Vec<$i> {
|
|
assert_eq!(a.len(), 2);
|
|
assert_eq!(a[0], 1 as $i);
|
|
assert_eq!(a[1], 2 as $i);
|
|
$js(a)
|
|
}
|
|
)*)
|
|
}
|
|
|
|
|
|
doit! {
|
|
(rust_i8, js_i8, i8)
|
|
(rust_u8, js_u8, u8)
|
|
(rust_i16, js_i16, i16)
|
|
(rust_u16, js_u16, u16)
|
|
(rust_i32, js_i32, i32)
|
|
(rust_u32, js_u32, u32)
|
|
(rust_f32, js_f32, f32)
|
|
(rust_f64, js_f64, f64)
|
|
}
|
|
"#)
|
|
.file("test.ts", r#"
|
|
import * as assert from "assert";
|
|
import * as wasm from "./out";
|
|
|
|
export function js_i8(a: any): any {
|
|
assert.strictEqual(a.length, 2);
|
|
assert.strictEqual(a[0], 1);
|
|
assert.strictEqual(a[1], 2);
|
|
return a;
|
|
}
|
|
|
|
export function js_u8(a: any): any {
|
|
assert.strictEqual(a.length, 2);
|
|
assert.strictEqual(a[0], 1);
|
|
assert.strictEqual(a[1], 2);
|
|
return a;
|
|
}
|
|
|
|
export function js_i16(a: any): any {
|
|
assert.strictEqual(a.length, 2);
|
|
assert.strictEqual(a[0], 1);
|
|
assert.strictEqual(a[1], 2);
|
|
return a;
|
|
}
|
|
|
|
export function js_u16(a: any): any {
|
|
assert.strictEqual(a.length, 2);
|
|
assert.strictEqual(a[0], 1);
|
|
assert.strictEqual(a[1], 2);
|
|
return a;
|
|
}
|
|
|
|
export function js_i32(a: any): any {
|
|
assert.strictEqual(a.length, 2);
|
|
assert.strictEqual(a[0], 1);
|
|
assert.strictEqual(a[1], 2);
|
|
return a;
|
|
}
|
|
|
|
export function js_u32(a: any): any {
|
|
assert.strictEqual(a.length, 2);
|
|
assert.strictEqual(a[0], 1);
|
|
assert.strictEqual(a[1], 2);
|
|
return a;
|
|
}
|
|
|
|
export function js_f32(a: any): any {
|
|
assert.strictEqual(a.length, 2);
|
|
assert.strictEqual(a[0], 1);
|
|
assert.strictEqual(a[1], 2);
|
|
return a;
|
|
}
|
|
|
|
export function js_f64(a: any): any {
|
|
assert.strictEqual(a.length, 2);
|
|
assert.strictEqual(a[0], 1);
|
|
assert.strictEqual(a[1], 2);
|
|
return a;
|
|
}
|
|
|
|
function assert_arrays_equal(a: any, b: any) {
|
|
console.log(a, b);
|
|
assert.strictEqual(a.length, b.length);
|
|
assert.strictEqual(a.byteLength, b.byteLength);
|
|
for (let i = 0; i < a.length; i++) {
|
|
assert.strictEqual(a[i], b[i]);
|
|
}
|
|
}
|
|
|
|
export function test() {
|
|
const i8 = new Int8Array(2);
|
|
i8[0] = 1;
|
|
i8[1] = 2;
|
|
assert_arrays_equal(wasm.rust_i8(i8), i8);
|
|
const u8 = new Uint8Array(2);
|
|
u8[0] = 1;
|
|
u8[1] = 2;
|
|
assert_arrays_equal(wasm.rust_u8(u8), u8);
|
|
|
|
const i16 = new Int16Array(2);
|
|
i16[0] = 1;
|
|
i16[1] = 2;
|
|
assert_arrays_equal(wasm.rust_i16(i16), i16);
|
|
const u16 = new Uint16Array(2);
|
|
u16[0] = 1;
|
|
u16[1] = 2;
|
|
assert_arrays_equal(wasm.rust_u16(u16), u16);
|
|
|
|
const i32 = new Int32Array(2);
|
|
i32[0] = 1;
|
|
i32[1] = 2;
|
|
assert_arrays_equal(wasm.rust_i32(i32), i32);
|
|
const u32 = new Uint32Array(2);
|
|
u32[0] = 1;
|
|
u32[1] = 2;
|
|
assert_arrays_equal(wasm.rust_u32(u32), u32);
|
|
|
|
const f32 = new Float32Array(2);
|
|
f32[0] = 1;
|
|
f32[1] = 2;
|
|
assert_arrays_equal(wasm.rust_f32(f32), f32);
|
|
const f64 = new Float64Array(2);
|
|
f64[0] = 1;
|
|
f64[1] = 2;
|
|
assert_arrays_equal(wasm.rust_f64(f64), f64);
|
|
}
|
|
"#)
|
|
.test();
|
|
}
|
|
|
|
#[test]
|
|
fn pass_array_works() {
|
|
project()
|
|
.file("src/lib.rs", r#"
|
|
#![feature(proc_macro, wasm_custom_section, wasm_import_module)]
|
|
|
|
extern crate wasm_bindgen;
|
|
|
|
use wasm_bindgen::prelude::*;
|
|
|
|
macro_rules! doit {
|
|
($(($rust:ident, $i:ident))*) => ($(
|
|
#[wasm_bindgen]
|
|
pub fn $rust(a: &[$i]) {
|
|
assert_eq!(a.len(), 2);
|
|
assert_eq!(a[0], 1 as $i);
|
|
assert_eq!(a[1], 2 as $i);
|
|
}
|
|
)*)
|
|
}
|
|
|
|
|
|
doit! {
|
|
(rust_i8, i8)
|
|
(rust_u8, u8)
|
|
(rust_i16, i16)
|
|
(rust_u16, u16)
|
|
(rust_i32, i32)
|
|
(rust_u32, u32)
|
|
(rust_f32, f32)
|
|
(rust_f64, f64)
|
|
}
|
|
"#)
|
|
.file("test.js", r#"
|
|
const wasm = require("./out");
|
|
|
|
module.exports.test = function() {
|
|
wasm.rust_i8([1, 2]);
|
|
wasm.rust_u8([1, 2]);
|
|
wasm.rust_i16([1, 2]);
|
|
wasm.rust_u16([1, 2]);
|
|
wasm.rust_i32([1, 2]);
|
|
wasm.rust_u32([1, 2]);
|
|
wasm.rust_f32([1, 2]);
|
|
wasm.rust_f64([1, 2]);
|
|
};
|
|
"#)
|
|
.test();
|
|
}
|
|
|
|
#[test]
|
|
fn import_mut() {
|
|
project()
|
|
.file("src/lib.rs", r#"
|
|
#![feature(proc_macro, wasm_custom_section, wasm_import_module)]
|
|
|
|
extern crate wasm_bindgen;
|
|
|
|
use wasm_bindgen::prelude::*;
|
|
|
|
macro_rules! doit {
|
|
($(($rust:ident, $js:ident, $i:ident))*) => (
|
|
$(
|
|
#[wasm_bindgen(module = "./test")]
|
|
extern {
|
|
fn $js(a: &mut [$i]);
|
|
}
|
|
|
|
fn $rust() {
|
|
let mut buf = [
|
|
1 as $i,
|
|
2 as $i,
|
|
3 as $i,
|
|
];
|
|
$js(&mut buf);
|
|
assert_eq!(buf[0], 4 as $i);
|
|
assert_eq!(buf[1], 5 as $i);
|
|
assert_eq!(buf[2], 3 as $i);
|
|
}
|
|
)*
|
|
|
|
#[wasm_bindgen]
|
|
pub fn run() {
|
|
$($rust();)*
|
|
}
|
|
)
|
|
}
|
|
|
|
|
|
doit! {
|
|
(rust_i8, js_i8, i8)
|
|
(rust_u8, js_u8, u8)
|
|
(rust_i16, js_i16, i16)
|
|
(rust_u16, js_u16, u16)
|
|
(rust_i32, js_i32, i32)
|
|
(rust_u32, js_u32, u32)
|
|
(rust_f32, js_f32, f32)
|
|
(rust_f64, js_f64, f64)
|
|
}
|
|
"#)
|
|
.file("test.ts", r#"
|
|
import * as assert from "assert";
|
|
import * as wasm from "./out";
|
|
|
|
function foo(a: any) {
|
|
assert.strictEqual(a.length, 3);
|
|
assert.strictEqual(a[0], 1);
|
|
assert.strictEqual(a[1], 2);
|
|
a[0] = 4;
|
|
a[1] = 5;
|
|
}
|
|
|
|
export const js_i8 = foo;
|
|
export const js_u8 = foo;
|
|
export const js_i16 = foo;
|
|
export const js_u16 = foo;
|
|
export const js_i32 = foo;
|
|
export const js_u32 = foo;
|
|
export const js_f32 = foo;
|
|
export const js_f64 = foo;
|
|
|
|
export function test() {
|
|
wasm.run();
|
|
}
|
|
"#)
|
|
.test();
|
|
}
|
|
|
|
#[test]
|
|
fn export_mut() {
|
|
project()
|
|
.file("src/lib.rs", r#"
|
|
#![feature(proc_macro, wasm_custom_section)]
|
|
|
|
extern crate wasm_bindgen;
|
|
|
|
use wasm_bindgen::prelude::*;
|
|
|
|
macro_rules! doit {
|
|
($($i:ident)*) => ($(
|
|
#[wasm_bindgen]
|
|
pub fn $i(a: &mut [$i]) {
|
|
assert_eq!(a.len(), 3);
|
|
assert_eq!(a[0], 1 as $i);
|
|
assert_eq!(a[1], 2 as $i);
|
|
assert_eq!(a[2], 3 as $i);
|
|
a[0] = 4 as $i;
|
|
a[1] = 5 as $i;
|
|
}
|
|
)*)
|
|
}
|
|
|
|
|
|
doit! { i8 u8 i16 u16 i32 u32 f32 f64 }
|
|
"#)
|
|
.file("test.ts", r#"
|
|
import * as assert from "assert";
|
|
import * as wasm from "./out";
|
|
|
|
function run(a: any, rust: any) {
|
|
assert.strictEqual(a.length, 3);
|
|
a[0] = 1;
|
|
a[1] = 2;
|
|
a[2] = 3;
|
|
console.log(a);
|
|
rust(a);
|
|
console.log(a);
|
|
assert.strictEqual(a.length, 3);
|
|
assert.strictEqual(a[0], 4);
|
|
assert.strictEqual(a[1], 5);
|
|
assert.strictEqual(a[2], 3);
|
|
}
|
|
|
|
export function test() {
|
|
run(new Int8Array(3), wasm.i8);
|
|
run(new Uint8Array(3), wasm.u8);
|
|
run(new Int16Array(3), wasm.i16);
|
|
run(new Uint16Array(3), wasm.u16);
|
|
run(new Int32Array(3), wasm.i32);
|
|
run(new Uint32Array(3), wasm.u32);
|
|
run(new Float32Array(3), wasm.f32);
|
|
run(new Float64Array(3), wasm.f64);
|
|
}
|
|
"#)
|
|
.test();
|
|
}
|
|
|
|
#[test]
|
|
fn return_vec_ok() {
|
|
project()
|
|
.file("src/lib.rs", r#"
|
|
#![feature(proc_macro, wasm_custom_section, wasm_import_module)]
|
|
extern crate wasm_bindgen;
|
|
|
|
use wasm_bindgen::prelude::*;
|
|
|
|
#[wasm_bindgen]
|
|
pub fn broken_vec() -> Vec<u32> {
|
|
vec![1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
}
|
|
|
|
#[wasm_bindgen]
|
|
pub fn web_main() -> Application {
|
|
Application::new()
|
|
}
|
|
|
|
#[wasm_bindgen]
|
|
pub struct Application {
|
|
thing: Vec<u32>,
|
|
}
|
|
|
|
#[wasm_bindgen]
|
|
impl Application {
|
|
pub fn new() -> Application {
|
|
let mut thing = vec![];
|
|
thing.push(0);
|
|
thing.push(0);
|
|
thing.push(0);
|
|
thing.push(0);
|
|
thing.push(0);
|
|
|
|
Application {
|
|
thing: thing
|
|
}
|
|
}
|
|
pub fn tick(&mut self) {
|
|
self.thing = self.thing.clone();
|
|
}
|
|
}
|
|
|
|
pub fn main() {
|
|
}
|
|
"#)
|
|
.file("test.ts", r#"
|
|
import * as assert from "assert";
|
|
import * as wasm from "./out";
|
|
|
|
|
|
export function test() {
|
|
let app = wasm.web_main();
|
|
|
|
for (let i = 0; i < 10; i++) {
|
|
app.tick();
|
|
let bad = wasm.broken_vec();
|
|
console.log("Received from rust:", i, bad);
|
|
assert.strictEqual(bad[0], 1);
|
|
assert.strictEqual(bad[1], 2);
|
|
assert.strictEqual(bad[2], 3);
|
|
assert.strictEqual(bad[3], 4);
|
|
assert.strictEqual(bad[4], 5);
|
|
assert.strictEqual(bad[5], 6);
|
|
assert.strictEqual(bad[6], 7);
|
|
assert.strictEqual(bad[7], 8);
|
|
assert.strictEqual(bad[8], 9);
|
|
}
|
|
}
|
|
"#)
|
|
.test();
|
|
}
|
|
|