diff --git a/src/js.rs b/src/js.rs index c3fa8e62..681e2d54 100644 --- a/src/js.rs +++ b/src/js.rs @@ -208,6 +208,25 @@ extern { pub fn entries(this: &Array) -> ArrayIterator; } +// Function +#[wasm_bindgen] +extern { + pub type JsFunction; + + /// The length property indicates the number of arguments expected by the function. + /// + /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/length + #[wasm_bindgen(method, getter, structural)] + pub fn length(this: &JsFunction) -> u32; + + /// A Function object's read-only name property indicates the function's name as specified when it was created + /// or "anonymous" for functions created anonymously. + /// + /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name + #[wasm_bindgen(method, getter, structural)] + pub fn name(this: &JsFunction) -> String; +} + // Object. #[wasm_bindgen] extern { diff --git a/tests/all/js_globals/JsFunction.rs b/tests/all/js_globals/JsFunction.rs new file mode 100644 index 00000000..9c1d4ece --- /dev/null +++ b/tests/all/js_globals/JsFunction.rs @@ -0,0 +1,84 @@ +#![allow(non_snake_case)] + +use project; + +#[test] +fn length() { + project() + .file("src/lib.rs", r#" + #![feature(proc_macro, wasm_custom_section)] + + extern crate wasm_bindgen; + use wasm_bindgen::prelude::*; + use wasm_bindgen::js; + + #[wasm_bindgen] + pub fn fn_length(this: &js::JsFunction) -> u32 { + this.length() + } + "#) + .file("test.ts", r#" + import * as assert from "assert"; + import * as wasm from "./out"; + + export function test() { + assert.equal(0, wasm.fn_length(() => {})); + assert.equal(1, wasm.fn_length((a: string) => console.log(a))); + assert.equal(2, wasm.fn_length((a: string, b: string) => console.log({ a, b }))); + + function fn0() {} + function fn1(a: string) { + console.log(a); + } + function fn2(a: string, b: string) { + console.log({ a, b }); + } + + assert.equal(0, wasm.fn_length(fn0)); + assert.equal(1, wasm.fn_length(fn1)); + assert.equal(2, wasm.fn_length(fn2)); + } + "#) + .test() +} + +#[test] +fn name() { + project() + .file("src/lib.rs", r#" + #![feature(proc_macro, wasm_custom_section)] + + extern crate wasm_bindgen; + use wasm_bindgen::prelude::*; + use wasm_bindgen::js; + + #[wasm_bindgen] + pub fn fn_name(this: &js::JsFunction) -> String { + this.name() + } + "#) + .file("test.ts", r#" + import * as assert from "assert"; + import * as wasm from "./out"; + + export function test() { + function namedFn() {} + assert.equal('namedFn', wasm.fn_name(namedFn)); + + assert.equal('bound namedFn', wasm.fn_name(namedFn.bind({}))); + + const obj = { + method: () => {} + } + assert.equal('method', wasm.fn_name(obj.method)); + + assert.equal('anonymous', wasm.fn_name(new Function())); + + assert.equal('', wasm.fn_name(() => {})); + + const closure = () => {}; + assert.equal('closure', wasm.fn_name(closure)); + } + "#) + .test() +} diff --git a/tests/all/js_globals/mod.rs b/tests/all/js_globals/mod.rs index b03c3ae4..abd47f7a 100644 --- a/tests/all/js_globals/mod.rs +++ b/tests/all/js_globals/mod.rs @@ -5,6 +5,7 @@ use super::project; mod Object; mod Array; mod ArrayIterator; +mod JsFunction; mod JsString; #[test]