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
//! This crate allows you to embed inline javascript in your Rust code for use with the
//! wasm32-unknown-unknown target. Crates also need to use the `embed_js_build` crate in their
//! build script (see that crate's documentation for more details). Crates that generate binaries
//! must also use `embed_js_build` in a post-build step to collect the generated accompanying
//! javascript from itself and all dependencies.
//!
//! See the documentation pages of the macros in this crate for more details and examples. The
//! embed_js repository also contains example projects.

#[allow(unused_imports)]
#[macro_use]
extern crate embed_js_derive;

#[doc(hidden)]
pub use embed_js_derive::*;

/// For every crate that uses the `js` macro directly, the `embed_js_preamble` macro must be called
/// at least once somewhere in the crate, for example
///
/// ```ignore
/// #[macro_use]
/// extern crate embed_js;
///
/// embed_js_preamble!();
///
/// #[no_mangle]
/// pub fn entry_point() {
///     js!({console.log("Hello world!");});
/// }
/// ```
///
/// You do not need to import `embed_js` at all in crates that only depend on crates that use the
/// `js` macro without directly calling it themselves.
#[macro_export]
macro_rules! embed_js_preamble {
    () => { include!(concat!(env!("OUT_DIR"), "/embed_js_preamble.rs")); }
}

/// Call javascript, inline.
///
/// This macro must not be called from within any other macro, otherwise it will fail to work.
///
/// The javascript written inside calls to this macro must adhere to some additional rules:
///
/// * Every statement must end in a semi-colon.
/// * No single-quote multi-character strings are allowed.
///
/// There are three forms for calling this macro:
///
/// * `js!([arg1 as type1, arg2 as type2, &arg3, *arg3 as type3, &mut **arg3, ...] -> ret_type { /*javascript*/ })`
///
///   In this form, you specify arguments and a return type. There are two categories of argument.
///
///   Arguments preceded by a `&` are references. These arguments may be any number of reference
///   operations (both immutable and mutable) on an identifier that has been dereferenced via `*`
///   some number of times (including zero). These arguments are passed to the JavaScript as pointers,
///   with type wasm type `i32`. These pointers can then be looked up in the wasm module memory buffer
///   to access the contents of the value referenced.
///
///   Other arguments take the form of a possibly dereferenced identifier followed by `as type`,
///   for some type `type`. Values are cast using `as` to this type before passing to the JavaScript.
///
///   Every type specified, including the return type, must be one of `i32`, `i64`,
///   `f32` or `f64`. These are the only raw types supported by WebAssembly for interop at the
///   moment. More complicated types are best passed by reference.
///
///   Examples:
///
///   ```ignore
///   let x = 2;
///   let y = js!([x as i32] -> i32 {
///       return x + 1;
///   });
///   // y is now 3
///   ```
///
///   ```ignore
///   let one_half = js!([] -> f64 {
///       return 1.0 / 2.0;
///   });
///   ```
///
/// * `js!([arg1 as type1, arg2 as type2, ...] { /*javascript*/ })`
///
///   Like the previous form, but without a return type. Any value returned from javascript is
///   discarded.
///
/// * `js!({ /*javascript*/ })`
///
///   No arguments or return type.
#[macro_export]
macro_rules! js {
    ([$($args:tt)*] $($tt:tt)*) => {{
        #[derive(EmbedJsDetail)]
        #[allow(dead_code)]
        enum EmbedJsStruct {
            Input = (stringify!([$($args)*] $($tt)*), 0).1
        }
        EmbedJsStruct::call($($args)*)
    }};
    ({$($tt:tt)*}) => {{
        #[derive(EmbedJsDetail)]
        #[allow(dead_code)]
        enum EmbedJsStruct {
            Input = (stringify!({$($tt)*}), 0).1
        }
        EmbedJsStruct::call()
    }};
}

/// Used to specify JavaScript that should be executed before the WebAssembly module is loaded.
/// This is useful for specifying functions that can be shared between instances of inline JS, or
/// set up other global state. This macro is used as a statement or at item level.
///
/// The order of evaluation at runtime is the same as the order of `include_js` calls in the source,
/// with all modules inlined. The order with respect to other crates is not specified.
///
/// Example:
///
/// ```ignore
/// include_js! {
///     window.my_global_function = function() {
///         alert("Hello World!");
///     };
/// }
/// ```
#[macro_export]
macro_rules! include_js {
    ($($tt:tt)*) => {}
}