mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-06-22 09:11:35 +00:00
Add support for optional numbers
This commit is contained in:
committed by
Alex Crichton
parent
2a6d98a6c9
commit
c49c18826d
@ -154,7 +154,27 @@ impl Descriptor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_64bit(&self) -> Option<bool> {
|
pub fn is_primitive(&self) -> bool {
|
||||||
|
match *self {
|
||||||
|
Descriptor::I32
|
||||||
|
| Descriptor::U32
|
||||||
|
| Descriptor::F32
|
||||||
|
| Descriptor::F64 => true,
|
||||||
|
_ => return false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_as_u32(&self) -> bool {
|
||||||
|
match *self {
|
||||||
|
Descriptor::I8
|
||||||
|
| Descriptor::U8
|
||||||
|
| Descriptor::I16
|
||||||
|
| Descriptor::U16 => true,
|
||||||
|
_ => return false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_64(&self) -> Option<bool> {
|
||||||
match *self {
|
match *self {
|
||||||
Descriptor::I64 => Some(true),
|
Descriptor::I64 => Some(true),
|
||||||
Descriptor::U64 => Some(false),
|
Descriptor::U64 => Some(false),
|
||||||
|
@ -192,7 +192,74 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if optional {
|
if optional {
|
||||||
bail!("unsupported optional argument to rust function {:?}", arg);
|
if arg.is_primitive() {
|
||||||
|
self.cx.expose_is_like_none();
|
||||||
|
self.js_arguments.push((name.clone(), "number".to_string()));
|
||||||
|
|
||||||
|
if self.cx.config.debug {
|
||||||
|
self.cx.expose_assert_num();
|
||||||
|
self.prelude(&format!(
|
||||||
|
"\n\
|
||||||
|
if (!isLikeNone({0})) {{\n\
|
||||||
|
_assertNum({0});\n\
|
||||||
|
}}\n\
|
||||||
|
",
|
||||||
|
name
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
self.rust_arguments.push(format!("!isLikeNone({0})", name));
|
||||||
|
self.rust_arguments.push(format!("isLikeNone({0}) ? 0 : {0}", name));
|
||||||
|
return Ok(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
if arg.is_as_u32() {
|
||||||
|
self.cx.expose_is_like_none();
|
||||||
|
self.js_arguments.push((name.clone(), "number".to_string()));
|
||||||
|
|
||||||
|
if self.cx.config.debug {
|
||||||
|
self.cx.expose_assert_num();
|
||||||
|
self.prelude(&format!(
|
||||||
|
"\n\
|
||||||
|
if (!isLikeNone({0})) {{\n\
|
||||||
|
_assertNum({0});\n\
|
||||||
|
}}\n\
|
||||||
|
",
|
||||||
|
name
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
self.rust_arguments.push(format!("isLikeNone({0}) ? 0xFFFFFF : {0}", name));
|
||||||
|
return Ok(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(signed) = arg.get_64() {
|
||||||
|
let f = if signed {
|
||||||
|
self.cx.expose_int64_cvt_shim()
|
||||||
|
} else {
|
||||||
|
self.cx.expose_uint64_cvt_shim()
|
||||||
|
};
|
||||||
|
self.cx.expose_uint32_memory();
|
||||||
|
self.cx.expose_global_argument_ptr()?;
|
||||||
|
self.js_arguments.push((name.clone(), "BigInt".to_string()));
|
||||||
|
self.prelude(&format!(
|
||||||
|
"\
|
||||||
|
{f}[0] = isLikeNone({name}) ? BigInt(0) : {name};\n\
|
||||||
|
const low{i} = isLikeNone({name}) ? 0 : u32CvtShim[0];\n\
|
||||||
|
const high{i} = isLikeNone({name}) ? 0 : u32CvtShim[1];\n\
|
||||||
|
",
|
||||||
|
i = i,
|
||||||
|
f = f,
|
||||||
|
name = name,
|
||||||
|
));
|
||||||
|
self.rust_arguments.push(format!("!isLikeNone({})", name));
|
||||||
|
self.rust_arguments.push(format!("0"));
|
||||||
|
self.rust_arguments.push(format!("low{}", i));
|
||||||
|
self.rust_arguments.push(format!("high{}", i));
|
||||||
|
return Ok(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
bail!("unsupported optional argument type for calling Rust function from JS: {:?}", arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(s) = arg.rust_struct() {
|
if let Some(s) = arg.rust_struct() {
|
||||||
@ -240,7 +307,7 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
|
|||||||
return Ok(self);
|
return Ok(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(signed) = arg.get_64bit() {
|
if let Some(signed) = arg.get_64() {
|
||||||
let f = if signed {
|
let f = if signed {
|
||||||
self.cx.expose_int64_cvt_shim()
|
self.cx.expose_int64_cvt_shim()
|
||||||
} else {
|
} else {
|
||||||
@ -252,15 +319,15 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
|
|||||||
self.prelude(&format!(
|
self.prelude(&format!(
|
||||||
"\
|
"\
|
||||||
{f}[0] = {name};\n\
|
{f}[0] = {name};\n\
|
||||||
const lo{i} = u32CvtShim[0];\n\
|
const low{i} = u32CvtShim[0];\n\
|
||||||
const hi{i} = u32CvtShim[1];\n\
|
const high{i} = u32CvtShim[1];\n\
|
||||||
",
|
",
|
||||||
i = i,
|
i = i,
|
||||||
f = f,
|
f = f,
|
||||||
name = name,
|
name = name,
|
||||||
));
|
));
|
||||||
self.rust_arguments.push(format!("lo{}", i));
|
self.rust_arguments.push(format!("low{}", i));
|
||||||
self.rust_arguments.push(format!("hi{}", i));
|
self.rust_arguments.push(format!("high{}", i));
|
||||||
return Ok(self);
|
return Ok(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -292,7 +359,7 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
|
|||||||
self.js_arguments.push((name.clone(), "string".to_string()));
|
self.js_arguments.push((name.clone(), "string".to_string()));
|
||||||
self.rust_arguments.push(format!("{}.codePointAt(0)", name))
|
self.rust_arguments.push(format!("{}.codePointAt(0)", name))
|
||||||
}
|
}
|
||||||
_ => bail!("unsupported argument to rust function {:?}", arg),
|
_ => bail!("unsupported argument type for calling Rust function from JS: {:?}", arg),
|
||||||
}
|
}
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
@ -348,7 +415,78 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if optional {
|
if optional {
|
||||||
bail!("unsupported optional argument to rust function {:?}", ty);
|
if ty.is_primitive() {
|
||||||
|
self.ret_ty = "number".to_string();
|
||||||
|
self.cx.expose_global_argument_ptr()?;
|
||||||
|
self.cx.expose_uint32_memory();
|
||||||
|
match ty {
|
||||||
|
Descriptor::I32 => self.cx.expose_int32_memory(),
|
||||||
|
Descriptor::U32 => (),
|
||||||
|
Descriptor::F32 => self.cx.expose_f32_memory(),
|
||||||
|
Descriptor::F64 => self.cx.expose_f64_memory(),
|
||||||
|
_ => (),
|
||||||
|
};
|
||||||
|
self.prelude("const retptr = globalArgumentPtr();");
|
||||||
|
self.rust_arguments.insert(0, "retptr".to_string());
|
||||||
|
self.ret_expr = format!(
|
||||||
|
"\
|
||||||
|
RET;\n\
|
||||||
|
const present = getUint32Memory()[retptr / 4];\n\
|
||||||
|
const value = {mem}[retptr / {size} + 1];\n\
|
||||||
|
return present === 0 ? undefined : value;\n\
|
||||||
|
",
|
||||||
|
size = match ty {
|
||||||
|
Descriptor::I32 => 4,
|
||||||
|
Descriptor::U32 => 4,
|
||||||
|
Descriptor::F32 => 4,
|
||||||
|
Descriptor::F64 => 8,
|
||||||
|
_ => unreachable!(),
|
||||||
|
},
|
||||||
|
mem = match ty {
|
||||||
|
Descriptor::I32 => "getInt32Memory()",
|
||||||
|
Descriptor::U32 => "getUint32Memory()",
|
||||||
|
Descriptor::F32 => "getFloat32Memory()",
|
||||||
|
Descriptor::F64 => "getFloat64Memory()",
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return Ok(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ty.is_as_u32() {
|
||||||
|
self.ret_ty = "number".to_string();
|
||||||
|
self.ret_expr = "
|
||||||
|
const ret = RET;
|
||||||
|
return ret === 0xFFFFFF ? undefined : ret;
|
||||||
|
".to_string();
|
||||||
|
return Ok(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(signed) = ty.get_64() {
|
||||||
|
self.ret_ty = "BigInt".to_string();
|
||||||
|
self.cx.expose_global_argument_ptr()?;
|
||||||
|
let f = if signed {
|
||||||
|
self.cx.expose_int64_memory();
|
||||||
|
"getInt64Memory"
|
||||||
|
} else {
|
||||||
|
self.cx.expose_uint64_memory();
|
||||||
|
"getUint64Memory"
|
||||||
|
};
|
||||||
|
self.prelude("const retptr = globalArgumentPtr();");
|
||||||
|
self.rust_arguments.insert(0, "retptr".to_string());
|
||||||
|
self.ret_expr = format!(
|
||||||
|
"\
|
||||||
|
RET;\n\
|
||||||
|
const present = getUint32Memory()[retptr / 4];\n\
|
||||||
|
const value = {}()[retptr / 8 + 1];\n\
|
||||||
|
return present === 0 ? undefined : value;\n\
|
||||||
|
",
|
||||||
|
f
|
||||||
|
);
|
||||||
|
return Ok(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
bail!("unsupported optional return type for calling Rust function from JS: {:?}", ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ty.is_ref_anyref() {
|
if ty.is_ref_anyref() {
|
||||||
@ -374,7 +512,7 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
|
|||||||
return Ok(self);
|
return Ok(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(signed) = ty.get_64bit() {
|
if let Some(signed) = ty.get_64() {
|
||||||
self.ret_ty = "BigInt".to_string();
|
self.ret_ty = "BigInt".to_string();
|
||||||
self.cx.expose_global_argument_ptr()?;
|
self.cx.expose_global_argument_ptr()?;
|
||||||
let f = if signed {
|
let f = if signed {
|
||||||
@ -405,7 +543,7 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
|
|||||||
self.ret_ty = "string".to_string();
|
self.ret_ty = "string".to_string();
|
||||||
self.ret_expr = format!("return String.fromCodePoint(RET);")
|
self.ret_expr = format!("return String.fromCodePoint(RET);")
|
||||||
}
|
}
|
||||||
_ => bail!("unsupported return from Rust to JS {:?}", ty),
|
_ => bail!("unsupported return type for calling Rust function from JS: {:?}", ty),
|
||||||
}
|
}
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
@ -132,25 +132,66 @@ impl<'a, 'b> Rust2Js<'a, 'b> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if optional {
|
if optional {
|
||||||
bail!("unsupported optional argument {:?}", arg);
|
if arg.is_primitive() {
|
||||||
|
let value = self.shim_argument();
|
||||||
|
self.js_arguments.push(format!(
|
||||||
|
"{present} === 0 ? undefined : {value}",
|
||||||
|
value = value,
|
||||||
|
present = abi,
|
||||||
|
));
|
||||||
|
return Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
if arg.is_as_u32() {
|
||||||
|
self.js_arguments.push(format!("{0} === 0xFFFFFF ? undefined : {0}", abi));
|
||||||
|
return Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(signed) = arg.get_64() {
|
||||||
|
let f = if signed {
|
||||||
|
self.cx.expose_int64_cvt_shim()
|
||||||
|
} else {
|
||||||
|
self.cx.expose_uint64_cvt_shim()
|
||||||
|
};
|
||||||
|
self.shim_argument();
|
||||||
|
let low = self.shim_argument();
|
||||||
|
let high = self.shim_argument();
|
||||||
|
let name = format!("n{}", abi);
|
||||||
|
self.prelude(&format!(
|
||||||
|
"\
|
||||||
|
u32CvtShim[0] = {present} === 0 ? 0 : {low};\n\
|
||||||
|
u32CvtShim[1] = {present} === 0 ? 0 : {high};\n\
|
||||||
|
const {name} = {present} === 0 ? undefined : {f}[0];\n\
|
||||||
|
",
|
||||||
|
present = abi,
|
||||||
|
low = low,
|
||||||
|
high = high,
|
||||||
|
f = f,
|
||||||
|
name = name,
|
||||||
|
));
|
||||||
|
self.js_arguments.push(name);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
bail!("unsupported optional argument type for calling JS function from Rust: {:?}", arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(signed) = arg.get_64bit() {
|
if let Some(signed) = arg.get_64() {
|
||||||
let f = if signed {
|
let f = if signed {
|
||||||
self.cx.expose_int64_cvt_shim()
|
self.cx.expose_int64_cvt_shim()
|
||||||
} else {
|
} else {
|
||||||
self.cx.expose_uint64_cvt_shim()
|
self.cx.expose_uint64_cvt_shim()
|
||||||
};
|
};
|
||||||
let hi = self.shim_argument();
|
let high = self.shim_argument();
|
||||||
let name = format!("n{}", abi);
|
let name = format!("n{}", abi);
|
||||||
self.prelude(&format!(
|
self.prelude(&format!(
|
||||||
"\
|
"\
|
||||||
u32CvtShim[0] = {lo};\n\
|
u32CvtShim[0] = {low};\n\
|
||||||
u32CvtShim[1] = {hi};\n\
|
u32CvtShim[1] = {high};\n\
|
||||||
const {name} = {f}[0];\n\
|
const {name} = {f}[0];\n\
|
||||||
",
|
",
|
||||||
lo = abi,
|
low = abi,
|
||||||
hi = hi,
|
high = high,
|
||||||
f = f,
|
f = f,
|
||||||
name = name,
|
name = name,
|
||||||
));
|
));
|
||||||
@ -257,10 +298,7 @@ impl<'a, 'b> Rust2Js<'a, 'b> {
|
|||||||
ref d if d.is_number() => abi,
|
ref d if d.is_number() => abi,
|
||||||
Descriptor::Boolean => format!("{} !== 0", abi),
|
Descriptor::Boolean => format!("{} !== 0", abi),
|
||||||
Descriptor::Char => format!("String.fromCodePoint({})", abi),
|
Descriptor::Char => format!("String.fromCodePoint({})", abi),
|
||||||
_ => bail!(
|
_ => bail!("unsupported argument type for calling JS function from Rust: {:?}", arg),
|
||||||
"unimplemented argument type in imported function: {:?}",
|
|
||||||
arg
|
|
||||||
),
|
|
||||||
};
|
};
|
||||||
self.js_arguments.push(invoc_arg);
|
self.js_arguments.push(invoc_arg);
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -320,13 +358,79 @@ impl<'a, 'b> Rust2Js<'a, 'b> {
|
|||||||
return Ok(())
|
return Ok(())
|
||||||
}
|
}
|
||||||
if optional {
|
if optional {
|
||||||
bail!("unsupported optional return type {:?}", ty);
|
if ty.is_primitive() {
|
||||||
|
self.cx.expose_is_like_none();
|
||||||
|
self.cx.expose_uint32_memory();
|
||||||
|
match ty {
|
||||||
|
Descriptor::I32 => self.cx.expose_int32_memory(),
|
||||||
|
Descriptor::U32 => (),
|
||||||
|
Descriptor::F32 => self.cx.expose_f32_memory(),
|
||||||
|
Descriptor::F64 => self.cx.expose_f64_memory(),
|
||||||
|
_ => (),
|
||||||
|
};
|
||||||
|
self.shim_arguments.insert(0, "ret".to_string());
|
||||||
|
self.ret_expr = format!(
|
||||||
|
"\
|
||||||
|
const val = JS;\n\
|
||||||
|
getUint32Memory()[ret / 4] = !isLikeNone(val);\n\
|
||||||
|
{mem}[ret / {size} + 1] = isLikeNone(val) ? 0 : val;\n\
|
||||||
|
",
|
||||||
|
size = match ty {
|
||||||
|
Descriptor::I32 => 4,
|
||||||
|
Descriptor::U32 => 4,
|
||||||
|
Descriptor::F32 => 4,
|
||||||
|
Descriptor::F64 => 8,
|
||||||
|
_ => unreachable!(),
|
||||||
|
},
|
||||||
|
mem = match ty {
|
||||||
|
Descriptor::I32 => "getInt32Memory()",
|
||||||
|
Descriptor::U32 => "getUint32Memory()",
|
||||||
|
Descriptor::F32 => "getFloat32Memory()",
|
||||||
|
Descriptor::F64 => "getFloat64Memory()",
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
if ty.is_as_u32() {
|
||||||
|
self.cx.expose_is_like_none();
|
||||||
|
self.ret_expr = "
|
||||||
|
const val = JS;
|
||||||
|
return isLikeNone(val) ? 0xFFFFFF : val;
|
||||||
|
".to_string();
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(signed) = ty.get_64() {
|
||||||
|
self.cx.expose_is_like_none();
|
||||||
|
self.cx.expose_uint32_memory();
|
||||||
|
let f = if signed {
|
||||||
|
self.cx.expose_int64_memory();
|
||||||
|
"getInt64Memory"
|
||||||
|
} else {
|
||||||
|
self.cx.expose_uint64_memory();
|
||||||
|
"getUint64Memory"
|
||||||
|
};
|
||||||
|
self.shim_arguments.insert(0, "ret".to_string());
|
||||||
|
self.ret_expr = format!(
|
||||||
|
"\
|
||||||
|
const val = JS;\n\
|
||||||
|
getUint32Memory()[ret / 4] = !isLikeNone(val);\n\
|
||||||
|
{}()[ret / 8 + 1] = isLikeNone(val) ? BigInt(0) : val;\n\
|
||||||
|
",
|
||||||
|
f
|
||||||
|
);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
bail!("unsupported optional return type for calling JS function from Rust: {:?}", ty);
|
||||||
}
|
}
|
||||||
if ty.is_number() {
|
if ty.is_number() {
|
||||||
self.ret_expr = "return JS;".to_string();
|
self.ret_expr = "return JS;".to_string();
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
if let Some(signed) = ty.get_64bit() {
|
if let Some(signed) = ty.get_64() {
|
||||||
let f = if signed {
|
let f = if signed {
|
||||||
self.cx.expose_int64_memory();
|
self.cx.expose_int64_memory();
|
||||||
"getInt64Memory"
|
"getInt64Memory"
|
||||||
@ -370,7 +474,7 @@ impl<'a, 'b> Rust2Js<'a, 'b> {
|
|||||||
self.ret_expr = match *ty {
|
self.ret_expr = match *ty {
|
||||||
Descriptor::Boolean => "return JS ? 1 : 0;".to_string(),
|
Descriptor::Boolean => "return JS ? 1 : 0;".to_string(),
|
||||||
Descriptor::Char => "return JS.codePointAt(0);".to_string(),
|
Descriptor::Char => "return JS.codePointAt(0);".to_string(),
|
||||||
_ => bail!("unimplemented return from JS to Rust: {:?}", ty),
|
_ => bail!("unsupported return type for calling JS function from Rust: {:?}", ty),
|
||||||
};
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1,2 +0,0 @@
|
|||||||
These webidl files are unavailable because web-sys will fail to build when a function has an
|
|
||||||
optional primitive parameter (e.g. `optional short`).
|
|
@ -67,6 +67,17 @@ global.UndefinedMethod = class UndefinedMethod {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
global.OptionalMethod = class OptionalMethod {
|
||||||
|
constructor() {}
|
||||||
|
opt(a) {
|
||||||
|
if (a == undefined) {
|
||||||
|
return undefined;
|
||||||
|
} else {
|
||||||
|
return a + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
global.Unforgeable = class Unforgeable {
|
global.Unforgeable = class Unforgeable {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.uno = 1;
|
this.uno = 1;
|
||||||
|
@ -55,6 +55,13 @@ fn one_method_using_an_undefined_import_doesnt_break_all_other_methods() {
|
|||||||
assert!(f.ok_method());
|
assert!(f.ok_method());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn optional_method() {
|
||||||
|
let f = OptionalMethod::new().unwrap();
|
||||||
|
assert!(f.opt(Some(15)) == Some(16));
|
||||||
|
assert!(f.opt(None) == None);
|
||||||
|
}
|
||||||
|
|
||||||
#[wasm_bindgen_test]
|
#[wasm_bindgen_test]
|
||||||
fn unforgeable_is_structural() {
|
fn unforgeable_is_structural() {
|
||||||
let f = Unforgeable::new().unwrap();
|
let f = Unforgeable::new().unwrap();
|
||||||
|
5
crates/webidl-tests/simple.webidl
vendored
5
crates/webidl-tests/simple.webidl
vendored
@ -30,6 +30,11 @@ interface UndefinedMethod {
|
|||||||
boolean bad_method(UndefinedType undef);
|
boolean bad_method(UndefinedType undef);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
[Constructor()]
|
||||||
|
interface OptionalMethod {
|
||||||
|
octet? opt(short? a);
|
||||||
|
};
|
||||||
|
|
||||||
[Constructor()]
|
[Constructor()]
|
||||||
interface Unforgeable {
|
interface Unforgeable {
|
||||||
[Unforgeable] readonly attribute short uno;
|
[Unforgeable] readonly attribute short uno;
|
||||||
|
@ -1,59 +1,118 @@
|
|||||||
use core::char;
|
use core::char;
|
||||||
use core::mem::{self, ManuallyDrop};
|
use core::mem::{self, ManuallyDrop};
|
||||||
|
|
||||||
use convert::slices::WasmSlice;
|
|
||||||
use convert::{Stack, FromWasmAbi, IntoWasmAbi, RefFromWasmAbi};
|
use convert::{Stack, FromWasmAbi, IntoWasmAbi, RefFromWasmAbi};
|
||||||
use convert::{OptionIntoWasmAbi, OptionFromWasmAbi};
|
use convert::{OptionIntoWasmAbi, OptionFromWasmAbi};
|
||||||
|
use convert::traits::WasmAbi;
|
||||||
use JsValue;
|
use JsValue;
|
||||||
|
|
||||||
macro_rules! simple {
|
#[repr(C)]
|
||||||
($($t:tt)*) => ($(
|
pub struct WasmOptionalI32 {
|
||||||
|
pub present: u32,
|
||||||
|
pub value: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl WasmAbi for WasmOptionalI32 {}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct WasmOptionalU32 {
|
||||||
|
pub present: u32,
|
||||||
|
pub value: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl WasmAbi for WasmOptionalU32 {}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct WasmOptionalF32 {
|
||||||
|
pub present: u32,
|
||||||
|
pub value: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl WasmAbi for WasmOptionalF32 {}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct WasmOptionalF64 {
|
||||||
|
pub present: u32,
|
||||||
|
pub value: f64,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl WasmAbi for WasmOptionalF64 {}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct Wasm64 {
|
||||||
|
pub low: u32,
|
||||||
|
pub high: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl WasmAbi for Wasm64 {}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct WasmOptional64 {
|
||||||
|
pub present: u32,
|
||||||
|
pub padding: u32,
|
||||||
|
pub low: u32,
|
||||||
|
pub high: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl WasmAbi for WasmOptional64 {}
|
||||||
|
|
||||||
|
macro_rules! type_primitive {
|
||||||
|
($($t:tt as $c:tt => $r:tt)*) => ($(
|
||||||
impl IntoWasmAbi for $t {
|
impl IntoWasmAbi for $t {
|
||||||
type Abi = $t;
|
type Abi = $c;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn into_abi(self, _extra: &mut Stack) -> $t { self }
|
fn into_abi(self, _extra: &mut Stack) -> $c { self as $c }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromWasmAbi for $t {
|
impl FromWasmAbi for $t {
|
||||||
type Abi = $t;
|
type Abi = $c;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn from_abi(js: $t, _extra: &mut Stack) -> $t { js }
|
unsafe fn from_abi(js: $c, _extra: &mut Stack) -> Self { js as $t }
|
||||||
}
|
}
|
||||||
)*)
|
|
||||||
}
|
|
||||||
|
|
||||||
simple!(u32 i32 f32 f64);
|
impl IntoWasmAbi for Option<$t> {
|
||||||
|
type Abi = $r;
|
||||||
|
|
||||||
macro_rules! sixtyfour {
|
fn into_abi(self, _extra: &mut Stack) -> $r {
|
||||||
($($t:tt)*) => ($(
|
match self {
|
||||||
impl IntoWasmAbi for $t {
|
None => $r {
|
||||||
type Abi = WasmSlice;
|
present: 0,
|
||||||
|
value: 0 as $c,
|
||||||
#[inline]
|
},
|
||||||
fn into_abi(self, _extra: &mut Stack) -> WasmSlice {
|
Some(me) => $r {
|
||||||
WasmSlice {
|
present: 1,
|
||||||
ptr: self as u32,
|
value: me as $c,
|
||||||
len: (self >> 32) as u32,
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromWasmAbi for $t {
|
impl FromWasmAbi for Option<$t> {
|
||||||
type Abi = WasmSlice;
|
type Abi = $r;
|
||||||
|
|
||||||
#[inline]
|
unsafe fn from_abi(js: $r, _extra: &mut Stack) -> Self {
|
||||||
unsafe fn from_abi(js: WasmSlice, _extra: &mut Stack) -> $t {
|
if js.present == 0 {
|
||||||
(js.ptr as $t) | ((js.len as $t) << 32)
|
None
|
||||||
|
} else {
|
||||||
|
Some(js.value as $t)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)*)
|
)*)
|
||||||
}
|
}
|
||||||
|
|
||||||
sixtyfour!(i64 u64);
|
type_primitive!(
|
||||||
|
i32 as i32 => WasmOptionalI32
|
||||||
|
isize as i32 => WasmOptionalI32
|
||||||
|
u32 as u32 => WasmOptionalU32
|
||||||
|
usize as u32 => WasmOptionalU32
|
||||||
|
f32 as f32 => WasmOptionalF32
|
||||||
|
f64 as f64 => WasmOptionalF64
|
||||||
|
);
|
||||||
|
|
||||||
macro_rules! as_u32 {
|
macro_rules! type_as_u32 {
|
||||||
($($t:tt)*) => ($(
|
($($t:tt)*) => ($(
|
||||||
impl IntoWasmAbi for $t {
|
impl IntoWasmAbi for $t {
|
||||||
type Abi = u32;
|
type Abi = u32;
|
||||||
@ -66,12 +125,82 @@ macro_rules! as_u32 {
|
|||||||
type Abi = u32;
|
type Abi = u32;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn from_abi(js: u32, _extra: &mut Stack) -> $t { js as $t }
|
unsafe fn from_abi(js: u32, _extra: &mut Stack) -> Self { js as $t }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OptionIntoWasmAbi for $t {
|
||||||
|
#[inline]
|
||||||
|
fn none() -> u32 { 0xFFFFFFu32 }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OptionFromWasmAbi for $t {
|
||||||
|
#[inline]
|
||||||
|
fn is_none(js: &u32) -> bool { *js == 0xFFFFFFu32 }
|
||||||
}
|
}
|
||||||
)*)
|
)*)
|
||||||
}
|
}
|
||||||
|
|
||||||
as_u32!(i8 u8 i16 u16 isize usize);
|
type_as_u32!(i8 u8 i16 u16);
|
||||||
|
|
||||||
|
macro_rules! type_64 {
|
||||||
|
($($t:tt)*) => ($(
|
||||||
|
impl IntoWasmAbi for $t {
|
||||||
|
type Abi = Wasm64;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn into_abi(self, _extra: &mut Stack) -> Wasm64 {
|
||||||
|
Wasm64 {
|
||||||
|
low: self as u32,
|
||||||
|
high: (self >> 32) as u32,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromWasmAbi for $t {
|
||||||
|
type Abi = Wasm64;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
unsafe fn from_abi(js: Wasm64, _extra: &mut Stack) -> $t {
|
||||||
|
(js.low as $t) | ((js.high as $t) << 32)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoWasmAbi for Option<$t> {
|
||||||
|
type Abi = WasmOptional64;
|
||||||
|
|
||||||
|
fn into_abi(self, _extra: &mut Stack) -> WasmOptional64 {
|
||||||
|
match self {
|
||||||
|
None => WasmOptional64 {
|
||||||
|
present: 0,
|
||||||
|
padding: 0,
|
||||||
|
low: 0 as u32,
|
||||||
|
high: 0 as u32,
|
||||||
|
},
|
||||||
|
Some(me) => WasmOptional64 {
|
||||||
|
present: 1,
|
||||||
|
padding: 0,
|
||||||
|
low: me as u32,
|
||||||
|
high: (me >> 32) as u32,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromWasmAbi for Option<$t> {
|
||||||
|
type Abi = WasmOptional64;
|
||||||
|
|
||||||
|
unsafe fn from_abi(js: WasmOptional64, _extra: &mut Stack) -> Self {
|
||||||
|
if js.present == 0 {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some((js.low as $t) | ((js.high as $t) << 32))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)*)
|
||||||
|
}
|
||||||
|
|
||||||
|
type_64!(i64 u64);
|
||||||
|
|
||||||
impl IntoWasmAbi for bool {
|
impl IntoWasmAbi for bool {
|
||||||
type Abi = u32;
|
type Abi = u32;
|
||||||
@ -185,8 +314,8 @@ impl<T: OptionIntoWasmAbi> IntoWasmAbi for Option<T> {
|
|||||||
|
|
||||||
fn into_abi(self, extra: &mut Stack) -> T::Abi {
|
fn into_abi(self, extra: &mut Stack) -> T::Abi {
|
||||||
match self {
|
match self {
|
||||||
Some(me) => me.into_abi(extra),
|
|
||||||
None => T::none(),
|
None => T::none(),
|
||||||
|
Some(me) => me.into_abi(extra),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ mod math;
|
|||||||
mod node;
|
mod node;
|
||||||
mod non_debug;
|
mod non_debug;
|
||||||
mod non_wasm;
|
mod non_wasm;
|
||||||
|
mod optional_numbers;
|
||||||
mod simple;
|
mod simple;
|
||||||
mod slice;
|
mod slice;
|
||||||
mod structural;
|
mod structural;
|
||||||
|
331
tests/all/optional_numbers.rs
Normal file
331
tests/all/optional_numbers.rs
Normal file
@ -0,0 +1,331 @@
|
|||||||
|
use super::project;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn works() {
|
||||||
|
project()
|
||||||
|
.requires_bigint()
|
||||||
|
.file(
|
||||||
|
"src/lib.rs",
|
||||||
|
r#"
|
||||||
|
#![feature(use_extern_macros)]
|
||||||
|
|
||||||
|
extern crate wasm_bindgen;
|
||||||
|
|
||||||
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
|
#[wasm_bindgen(module = "./test")]
|
||||||
|
extern {
|
||||||
|
fn i32_js_identity(a: Option<i32>) -> Option<i32>;
|
||||||
|
}
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn i32_none() -> Option<i32> { None }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn i32_zero() -> Option<i32> { Some(0) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn i32_one() -> Option<i32> { Some(1) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn i32_neg_one() -> Option<i32> { Some(-1) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn i32_max() -> Option<i32> { Some(i32::max_value()) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn i32_min() -> Option<i32> { Some(i32::min_value()) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn i32_identity(a: Option<i32>) -> Option<i32> { i32_js_identity(a) }
|
||||||
|
|
||||||
|
#[wasm_bindgen(module = "./test")]
|
||||||
|
extern {
|
||||||
|
fn u32_js_identity(a: Option<u32>) -> Option<u32>;
|
||||||
|
}
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn u32_none() -> Option<u32> { None }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn u32_zero() -> Option<u32> { Some(0) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn u32_one() -> Option<u32> { Some(1) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn u32_max() -> Option<u32> { Some(u32::max_value()) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn u32_min() -> Option<u32> { Some(u32::min_value()) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn u32_identity(a: Option<u32>) -> Option<u32> { u32_js_identity(a) }
|
||||||
|
|
||||||
|
#[wasm_bindgen(module = "./test")]
|
||||||
|
extern {
|
||||||
|
fn isize_js_identity(a: Option<isize>) -> Option<isize>;
|
||||||
|
}
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn isize_none() -> Option<isize> { None }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn isize_zero() -> Option<isize> { Some(0) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn isize_one() -> Option<isize> { Some(1) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn isize_neg_one() -> Option<isize> { Some(-1) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn isize_max() -> Option<isize> { Some(isize::max_value()) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn isize_min() -> Option<isize> { Some(isize::min_value()) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn isize_identity(a: Option<isize>) -> Option<isize> { isize_js_identity(a) }
|
||||||
|
|
||||||
|
#[wasm_bindgen(module = "./test")]
|
||||||
|
extern {
|
||||||
|
fn usize_js_identity(a: Option<usize>) -> Option<usize>;
|
||||||
|
}
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn usize_none() -> Option<usize> { None }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn usize_zero() -> Option<usize> { Some(0) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn usize_one() -> Option<usize> { Some(1) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn usize_max() -> Option<usize> { Some(usize::max_value()) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn usize_min() -> Option<usize> { Some(usize::min_value()) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn usize_identity(a: Option<usize>) -> Option<usize> { usize_js_identity(a) }
|
||||||
|
|
||||||
|
#[wasm_bindgen(module = "./test")]
|
||||||
|
extern {
|
||||||
|
fn f32_js_identity(a: Option<f32>) -> Option<f32>;
|
||||||
|
}
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn f32_none() -> Option<f32> { None }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn f32_zero() -> Option<f32> { Some(0f32) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn f32_one() -> Option<f32> { Some(1f32) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn f32_neg_one() -> Option<f32> { Some(-1f32) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn f32_identity(a: Option<f32>) -> Option<f32> { f32_js_identity(a) }
|
||||||
|
|
||||||
|
#[wasm_bindgen(module = "./test")]
|
||||||
|
extern {
|
||||||
|
fn f64_js_identity(a: Option<f64>) -> Option<f64>;
|
||||||
|
}
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn f64_none() -> Option<f64> { None }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn f64_zero() -> Option<f64> { Some(0f64) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn f64_one() -> Option<f64> { Some(1f64) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn f64_neg_one() -> Option<f64> { Some(-1f64) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn f64_identity(a: Option<f64>) -> Option<f64> { f64_js_identity(a) }
|
||||||
|
|
||||||
|
#[wasm_bindgen(module = "./test")]
|
||||||
|
extern {
|
||||||
|
fn i8_js_identity(a: Option<i8>) -> Option<i8>;
|
||||||
|
}
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn i8_none() -> Option<i8> { None }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn i8_zero() -> Option<i8> { Some(0) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn i8_one() -> Option<i8> { Some(1) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn i8_neg_one() -> Option<i8> { Some(-1) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn i8_max() -> Option<i8> { Some(i8::max_value()) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn i8_min() -> Option<i8> { Some(i8::min_value()) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn i8_identity(a: Option<i8>) -> Option<i8> { i8_js_identity(a) }
|
||||||
|
|
||||||
|
#[wasm_bindgen(module = "./test")]
|
||||||
|
extern {
|
||||||
|
fn u8_js_identity(a: Option<u8>) -> Option<u8>;
|
||||||
|
}
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn u8_none() -> Option<u8> { None }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn u8_zero() -> Option<u8> { Some(0) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn u8_one() -> Option<u8> { Some(1) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn u8_max() -> Option<u8> { Some(u8::max_value()) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn u8_min() -> Option<u8> { Some(u8::min_value()) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn u8_identity(a: Option<u8>) -> Option<u8> { u8_js_identity(a) }
|
||||||
|
|
||||||
|
#[wasm_bindgen(module = "./test")]
|
||||||
|
extern {
|
||||||
|
fn i16_js_identity(a: Option<i16>) -> Option<i16>;
|
||||||
|
}
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn i16_none() -> Option<i16> { None }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn i16_zero() -> Option<i16> { Some(0) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn i16_one() -> Option<i16> { Some(1) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn i16_neg_one() -> Option<i16> { Some(-1) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn i16_max() -> Option<i16> { Some(i16::max_value()) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn i16_min() -> Option<i16> { Some(i16::min_value()) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn i16_identity(a: Option<i16>) -> Option<i16> { i16_js_identity(a) }
|
||||||
|
|
||||||
|
#[wasm_bindgen(module = "./test")]
|
||||||
|
extern {
|
||||||
|
fn u16_js_identity(a: Option<u16>) -> Option<u16>;
|
||||||
|
}
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn u16_none() -> Option<u16> { None }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn u16_zero() -> Option<u16> { Some(0) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn u16_one() -> Option<u16> { Some(1) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn u16_max() -> Option<u16> { Some(u16::max_value()) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn u16_min() -> Option<u16> { Some(u16::min_value()) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn u16_identity(a: Option<u16>) -> Option<u16> { u16_js_identity(a) }
|
||||||
|
|
||||||
|
#[wasm_bindgen(module = "./test")]
|
||||||
|
extern {
|
||||||
|
fn i64_js_identity(a: Option<i64>) -> Option<i64>;
|
||||||
|
}
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn i64_none() -> Option<i64> { None }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn i64_zero() -> Option<i64> { Some(0) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn i64_one() -> Option<i64> { Some(1) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn i64_neg_one() -> Option<i64> { Some(-1) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn i64_max() -> Option<i64> { Some(i64::max_value()) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn i64_min() -> Option<i64> { Some(i64::min_value()) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn i64_identity(a: Option<i64>) -> Option<i64> { i64_js_identity(a) }
|
||||||
|
|
||||||
|
#[wasm_bindgen(module = "./test")]
|
||||||
|
extern {
|
||||||
|
fn u64_js_identity(a: Option<u64>) -> Option<u64>;
|
||||||
|
}
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn u64_none() -> Option<u64> { None }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn u64_zero() -> Option<u64> { Some(0) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn u64_one() -> Option<u64> { Some(1) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn u64_max() -> Option<u64> { Some(u64::max_value()) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn u64_min() -> Option<u64> { Some(u64::min_value()) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn u64_identity(a: Option<u64>) -> Option<u64> { u64_js_identity(a) }
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.file(
|
||||||
|
"test.js",
|
||||||
|
r#"
|
||||||
|
import * as wasm from './out';
|
||||||
|
|
||||||
|
function assertEq(a, b) {
|
||||||
|
console.log(a, '?=', b);
|
||||||
|
if (a === b)
|
||||||
|
return;
|
||||||
|
throw new Error('not equal');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function test() {
|
||||||
|
assertEq(wasm.i32_identity(wasm.i32_none()), undefined);
|
||||||
|
assertEq(wasm.i32_identity(wasm.i32_zero()), 0);
|
||||||
|
assertEq(wasm.i32_identity(wasm.i32_one()), 1);
|
||||||
|
assertEq(wasm.i32_identity(wasm.i32_neg_one()), -1);
|
||||||
|
assertEq(wasm.i32_identity(wasm.i32_max()), 2147483647);
|
||||||
|
assertEq(wasm.i32_identity(wasm.i32_min()), -2147483648);
|
||||||
|
|
||||||
|
assertEq(wasm.u32_identity(wasm.u32_none()), undefined);
|
||||||
|
assertEq(wasm.u32_identity(wasm.u32_zero()), 0);
|
||||||
|
assertEq(wasm.u32_identity(wasm.u32_one()), 1);
|
||||||
|
assertEq(wasm.u32_identity(wasm.u32_max()), 4294967295);
|
||||||
|
assertEq(wasm.u32_identity(wasm.u32_min()), 0);
|
||||||
|
|
||||||
|
assertEq(wasm.isize_identity(wasm.isize_none()), undefined);
|
||||||
|
assertEq(wasm.isize_identity(wasm.isize_zero()), 0);
|
||||||
|
assertEq(wasm.isize_identity(wasm.isize_one()), 1);
|
||||||
|
assertEq(wasm.isize_identity(wasm.isize_neg_one()), -1);
|
||||||
|
assertEq(wasm.isize_identity(wasm.isize_max()), 2147483647);
|
||||||
|
assertEq(wasm.isize_identity(wasm.isize_min()), -2147483648);
|
||||||
|
|
||||||
|
assertEq(wasm.usize_identity(wasm.usize_none()), undefined);
|
||||||
|
assertEq(wasm.usize_identity(wasm.usize_zero()), 0);
|
||||||
|
assertEq(wasm.usize_identity(wasm.usize_one()), 1);
|
||||||
|
assertEq(wasm.usize_identity(wasm.usize_max()), 4294967295);
|
||||||
|
assertEq(wasm.usize_identity(wasm.usize_min()), 0);
|
||||||
|
|
||||||
|
assertEq(wasm.f32_identity(wasm.f32_none()), undefined);
|
||||||
|
assertEq(wasm.f32_identity(wasm.f32_zero()), 0);
|
||||||
|
assertEq(wasm.f32_identity(wasm.f32_one()), 1);
|
||||||
|
assertEq(wasm.f32_identity(wasm.f32_neg_one()), -1);
|
||||||
|
|
||||||
|
assertEq(wasm.f64_identity(wasm.f64_none()), undefined);
|
||||||
|
assertEq(wasm.f64_identity(wasm.f64_zero()), 0);
|
||||||
|
assertEq(wasm.f64_identity(wasm.f64_one()), 1);
|
||||||
|
assertEq(wasm.f64_identity(wasm.f64_neg_one()), -1);
|
||||||
|
|
||||||
|
assertEq(wasm.i8_identity(wasm.i8_none()), undefined);
|
||||||
|
assertEq(wasm.i8_identity(wasm.i8_zero()), 0);
|
||||||
|
assertEq(wasm.i8_identity(wasm.i8_one()), 1);
|
||||||
|
assertEq(wasm.i8_identity(wasm.i8_neg_one()), -1);
|
||||||
|
assertEq(wasm.i8_identity(wasm.i8_max()), 127);
|
||||||
|
assertEq(wasm.i8_identity(wasm.i8_min()), -128);
|
||||||
|
|
||||||
|
assertEq(wasm.u8_identity(wasm.u8_none()), undefined);
|
||||||
|
assertEq(wasm.u8_identity(wasm.u8_zero()), 0);
|
||||||
|
assertEq(wasm.u8_identity(wasm.u8_one()), 1);
|
||||||
|
assertEq(wasm.u8_identity(wasm.u8_max()), 255);
|
||||||
|
assertEq(wasm.u8_identity(wasm.u8_min()), 0);
|
||||||
|
|
||||||
|
assertEq(wasm.i16_identity(wasm.i16_none()), undefined);
|
||||||
|
assertEq(wasm.i16_identity(wasm.i16_zero()), 0);
|
||||||
|
assertEq(wasm.i16_identity(wasm.i16_one()), 1);
|
||||||
|
assertEq(wasm.i16_identity(wasm.i16_neg_one()), -1);
|
||||||
|
assertEq(wasm.i16_identity(wasm.i16_max()), 32767);
|
||||||
|
assertEq(wasm.i16_identity(wasm.i16_min()), -32768);
|
||||||
|
|
||||||
|
assertEq(wasm.u16_identity(wasm.u16_none()), undefined);
|
||||||
|
assertEq(wasm.u16_identity(wasm.u16_zero()), 0);
|
||||||
|
assertEq(wasm.u16_identity(wasm.u16_one()), 1);
|
||||||
|
assertEq(wasm.u16_identity(wasm.u16_max()), 65535);
|
||||||
|
assertEq(wasm.u16_identity(wasm.u16_min()), 0);
|
||||||
|
|
||||||
|
assertEq(wasm.i64_identity(wasm.i64_none()), undefined);
|
||||||
|
assertEq(wasm.i64_identity(wasm.i64_zero()), BigInt("0"));
|
||||||
|
assertEq(wasm.i64_identity(wasm.i64_one()), BigInt("1"));
|
||||||
|
assertEq(wasm.i64_identity(wasm.i64_neg_one()), BigInt("-1"));
|
||||||
|
assertEq(wasm.i64_identity(wasm.i64_max()), BigInt("9223372036854775807"));
|
||||||
|
assertEq(wasm.i64_identity(wasm.i64_min()), BigInt("-9223372036854775808"));
|
||||||
|
|
||||||
|
assertEq(wasm.u64_identity(wasm.u64_none()), undefined);
|
||||||
|
assertEq(wasm.u64_identity(wasm.u64_zero()), BigInt("0"));
|
||||||
|
assertEq(wasm.u64_identity(wasm.u64_one()), BigInt("1"));
|
||||||
|
assertEq(wasm.u64_identity(wasm.u64_max()), BigInt("18446744073709551615"));
|
||||||
|
assertEq(wasm.u64_identity(wasm.u64_min()), BigInt("0"));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function i32_js_identity(a) { return a; }
|
||||||
|
export function u32_js_identity(a) { return a; }
|
||||||
|
export function isize_js_identity(a) { return a; }
|
||||||
|
export function usize_js_identity(a) { return a; }
|
||||||
|
export function f32_js_identity(a) { return a; }
|
||||||
|
export function f64_js_identity(a) { return a; }
|
||||||
|
export function i8_js_identity(a) { return a; }
|
||||||
|
export function u8_js_identity(a) { return a; }
|
||||||
|
export function i16_js_identity(a) { return a; }
|
||||||
|
export function u16_js_identity(a) { return a; }
|
||||||
|
export function i64_js_identity(a) { return a; }
|
||||||
|
export function u64_js_identity(a) { return a; }
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.test();
|
||||||
|
}
|
Reference in New Issue
Block a user