stdweb/
lib.rs

1//! The goal of this crate is to provide Rust bindings to the Web APIs and to allow
2//! a high degree of interoperability between Rust and JavaScript.
3//!
4//! ## Examples
5//!
6//! You can directly embed JavaScript code into Rust:
7//!
8//! ```rust
9//! let message = "Hello, 世界!";
10//! let result = js! {
11//!     alert( @{message} );
12//!     return 2 + 2 * 2;
13//! };
14//!
15//! println!( "2 + 2 * 2 = {:?}", result );
16//! ```
17//!
18//! Closures are also supported:
19//!
20//! ```rust
21//! let print_hello = |name: String| {
22//!     println!( "Hello, {}!", name );
23//! };
24//!
25//! js! {
26//!     var print_hello = @{print_hello};
27//!     print_hello( "Bob" );
28//!     print_hello.drop(); // Necessary to clean up the closure on Rust's side.
29//! }
30//! ```
31//!
32//! You can also pass arbitrary structures thanks to [serde]:
33//!
34//! ```rust
35//! #[derive(Serialize)]
36//! struct Person {
37//!     name: String,
38//!     age: i32
39//! }
40//!
41//! js_serializable!( Person );
42//!
43//! js! {
44//!     var person = @{person};
45//!     console.log( person.name + " is " + person.age + " years old." );
46//! };
47//! ```
48//!
49//! [serde]: https://serde.rs/
50//!
51//! This crate also exposes a number of Web APIs, for example:
52//!
53//! ```rust
54//! let button = document().query_selector( "#hide-button" ).unwrap().unwrap();
55//! button.add_event_listener( move |_: ClickEvent| {
56//!     for anchor in document().query_selector_all( "#main a" ) {
57//!         js!( @{anchor}.style = "display: none;"; );
58//!     }
59//! });
60//! ```
61//!
62//! Exposing Rust functions to JavaScript is supported too:
63//!
64//! ```rust
65//! #[js_export]
66//! fn hash( string: String ) -> String {
67//!     let mut hasher = Sha1::new();
68//!     hasher.update( string.as_bytes() );
69//!     hasher.digest().to_string()
70//! }
71//! ```
72//!
73//! Then you can do this from Node.js:
74//!
75//! ```js
76//! var hasher = require( "hasher.js" ); // Where `hasher.js` is generated from Rust code.
77//! console.log( hasher.hash( "Hello world!" ) );
78//! ```
79//!
80//! Or you can take the same `.js` file and use it in a web browser:
81//!
82//! ```html
83//! <script src="hasher.js"></script>
84//! <script>
85//!     Rust.hasher.then( function( hasher ) {
86//!         console.log( hasher.hash( "Hello world!" ) );
87//!     });
88//! </script>
89//! ```
90//!
91//! If you're using [Parcel] you can also use our [experimental Parcel plugin];
92//! first do this in your existing Parcel project:
93//!
94//!     $ npm install --save parcel-plugin-cargo-web
95//!
96//! And then simply:
97//!
98//! ```js
99//! import hasher from "./hasher/Cargo.toml";
100//! console.log( hasher.hash( "Hello world!" ) );
101//! ```
102//!
103//! [Parcel]: https://parceljs.org/
104//! [experimental Parcel plugin]: https://github.com/koute/parcel-plugin-cargo-web
105
106#![deny(
107    missing_docs,
108    missing_debug_implementations,
109    trivial_numeric_casts,
110    unused_import_braces
111)]
112#![cfg_attr(
113    all(test, rust_nightly),
114    feature(linkage) // Needed for async tests.
115)]
116#![cfg_attr(rust_nightly, feature(core_intrinsics))]
117#![cfg_attr(feature = "nightly", feature(never_type))]
118#![recursion_limit="1500"]
119
120#[cfg(feature = "serde")]
121#[macro_use]
122extern crate serde as serde_crate;
123
124#[cfg(any(test, feature = "serde_json"))]
125extern crate serde_json;
126
127#[cfg(all(test, feature = "serde"))]
128#[macro_use]
129extern crate serde_derive;
130
131#[cfg(all(target_arch = "wasm32", target_vendor = "unknown", target_os = "unknown", not(cargo_web)))]
132extern crate wasm_bindgen;
133
134#[cfg(all(target_arch = "wasm32", target_vendor = "unknown", target_os = "unknown", not(cargo_web), test))]
135#[macro_use]
136extern crate wasm_bindgen_test;
137
138#[cfg(all(target_arch = "wasm32", target_vendor = "unknown", target_os = "unknown", not(cargo_web), test))]
139#[macro_use]
140extern crate stdweb_internal_test_macro;
141
142extern crate stdweb_internal_macros;
143
144#[cfg(all(
145    target_arch = "wasm32",
146    target_os = "unknown"
147))]
148pub use stdweb_internal_macros::js_export;
149
150pub use stdweb_internal_macros::async_test;
151
152#[cfg(feature = "futures-support")]
153extern crate futures_core;
154
155#[cfg(feature = "futures-support")]
156extern crate futures_util;
157
158#[cfg(feature = "futures-support")]
159extern crate futures_channel;
160
161#[cfg(feature = "futures-support")]
162extern crate futures_executor;
163
164#[macro_use]
165extern crate stdweb_derive;
166#[macro_use]
167extern crate stdweb_internal_runtime;
168
169extern crate discard;
170
171#[cfg(all(target_arch = "wasm32", target_vendor = "unknown", target_os = "unknown", not(cargo_web), test))]
172wasm_bindgen_test_configure!( run_in_browser );
173
174#[macro_use]
175mod webcore;
176mod webapi;
177mod ecosystem;
178
179// This is here so that our procedural macros
180// can work within the crate.
181pub(crate) mod stdweb {
182    pub use super::*;
183}
184
185pub use webcore::initialization::{
186    initialize,
187    event_loop
188};
189pub use webcore::value::{
190    Undefined,
191    Null,
192    Value,
193    Reference
194};
195pub use webcore::number::Number;
196pub use webcore::object::Object;
197pub use webcore::array::Array;
198pub use webcore::symbol::Symbol;
199
200pub use webcore::unsafe_typed_array::UnsafeTypedArray;
201pub use webcore::mutfn::Mut;
202pub use webcore::once::Once;
203pub use webcore::instance_of::InstanceOf;
204pub use webcore::reference_type::ReferenceType;
205pub use webcore::serialization::JsSerialize;
206
207pub use webcore::discard::DiscardOnDrop;
208
209#[cfg(feature = "experimental_features_which_may_break_on_minor_version_bumps")]
210pub use webcore::promise::{TypedPromise, Promise, DoneHandle};
211
212#[cfg(all(
213    feature = "futures-support",
214    feature = "experimental_features_which_may_break_on_minor_version_bumps"
215))]
216pub use webcore::promise_future::{PromiseFuture, spawn_local, print_error_panic, unwrap_future};
217
218#[cfg(feature = "serde")]
219/// A module with serde-related APIs.
220pub mod serde {
221    pub use ecosystem::serde::{
222        ConversionError,
223        Serde
224    };
225}
226
227/// A module with bindings to the Web APIs.
228pub mod web {
229    #[cfg(feature = "futures-support")]
230    pub use webapi::timer_future::{
231        Wait,
232        wait,
233        IntervalBuffered,
234        interval_buffered
235    };
236
237    pub use webapi::window::{
238        Window,
239        window
240    };
241    pub use webapi::document::{
242        Document,
243        document
244    };
245    pub use webapi::global::{
246        set_timeout,
247        alert,
248        confirm
249    };
250    pub use webapi::cross_origin_setting::CrossOriginSetting;
251    pub use webapi::date::Date;
252    pub use webapi::event_target::{IEventTarget, EventTarget, EventListenerHandle};
253    pub use webapi::window::RequestAnimationFrameHandle;
254    pub use webapi::node::{INode, Node, CloneKind, NodeType};
255    pub use webapi::element::{IElement, Element};
256    pub use webapi::document_fragment::DocumentFragment;
257    pub use webapi::text_node::TextNode;
258    pub use webapi::html_element::{IHtmlElement, HtmlElement, Rect};
259    pub use webapi::window_or_worker::IWindowOrWorker;
260    pub use webapi::parent_node::IParentNode;
261    pub use webapi::slotable::ISlotable;
262    pub use webapi::non_element_parent_node::INonElementParentNode;
263    pub use webapi::token_list::TokenList;
264    pub use webapi::node_list::NodeList;
265    pub use webapi::string_map::StringMap;
266    pub use webapi::storage::Storage;
267    pub use webapi::location::Location;
268    pub use webapi::array_buffer::ArrayBuffer;
269    pub use webapi::typed_array::TypedArray;
270    pub use webapi::file::File;
271    pub use webapi::file_reader::{FileReader, FileReaderResult, FileReaderReadyState};
272    pub use webapi::file_list::FileList;
273    pub use webapi::history::History;
274    pub use webapi::web_socket::{WebSocket, SocketCloseCode, SocketBinaryType, SocketReadyState};
275    pub use webapi::rendering_context::{RenderingContext, CanvasRenderingContext2d, CanvasGradient, CanvasPattern, CanvasStyle, CompositeOperation, FillRule, ImageData, LineCap, LineJoin, Repetition, TextAlign, TextBaseline, TextMetrics};
276    pub use webapi::mutation_observer::{MutationObserver, MutationObserverHandle, MutationObserverInit, MutationRecord};
277    pub use webapi::xml_http_request::{XmlHttpRequest, XhrReadyState, XhrResponseType};
278    pub use webapi::blob::{IBlob, Blob};
279    pub use webapi::html_collection::HtmlCollection;
280    pub use webapi::child_node::IChildNode;
281    pub use webapi::gamepad::{Gamepad, GamepadButton, GamepadMappingType};
282    pub use webapi::touch::{Touch, TouchType};
283    pub use webapi::selection::Selection;
284    pub use webapi::shadow_root::{ShadowRootMode, ShadowRoot};
285    pub use webapi::html_elements::SlotContentKind;
286    pub use webapi::form_data::{FormData, FormDataEntry};
287    pub use webapi::window_or_worker::TimeoutHandle;
288
289    /// A module containing error types.
290    pub mod error {
291        pub use webapi::dom_exception::{
292            IDomException,
293            DomException,
294            HierarchyRequestError,
295            IndexSizeError,
296            InvalidAccessError,
297            InvalidStateError,
298            NotFoundError,
299            NotSupportedError,
300            SecurityError,
301            SyntaxError,
302            InvalidCharacterError,
303            AbortError
304        };
305
306        pub use webapi::error::{
307            IError,
308            Error,
309            TypeError
310        };
311
312        pub use webapi::rendering_context::{AddColorStopError, DrawImageError, GetImageDataError};
313        pub use webapi::html_elements::UnknownValueError;
314        pub use webapi::xml_http_request::XhrSetResponseTypeError;
315    }
316
317    /// A module containing HTML DOM elements.
318    pub mod html_element {
319        pub use webapi::html_elements::ImageElement;
320        pub use webapi::html_elements::InputElement;
321        pub use webapi::html_elements::TextAreaElement;
322        pub use webapi::html_elements::CanvasElement;
323        pub use webapi::html_elements::SelectElement;
324        pub use webapi::html_elements::OptionElement;
325        pub use webapi::html_elements::TemplateElement;
326        pub use webapi::html_elements::SlotElement;
327    }
328
329    /// A module containing JavaScript DOM events.
330    pub mod event {
331        pub use webapi::event::{
332            IEvent,
333            IUiEvent,
334            ConcreteEvent,
335
336            UnloadEvent,
337            BeforeUnloadEvent,
338
339            FullscreenChangeEvent,
340
341            EventPhase
342        };
343
344        pub use webapi::events::mouse::{
345            IMouseEvent,
346            ClickEvent,
347            AuxClickEvent,
348            ContextMenuEvent,
349            DoubleClickEvent,
350            MouseDownEvent,
351            MouseUpEvent,
352            MouseMoveEvent,
353            MouseOverEvent,
354            MouseOutEvent,
355            MouseEnterEvent,
356            MouseLeaveEvent,
357            MouseWheelEvent,
358            MouseWheelDeltaMode,
359            MouseButton,
360            MouseButtonsState
361        };
362
363        pub use webapi::events::touch::{
364            ITouchEvent,
365            TouchEvent,
366            TouchMove,
367            TouchLeave,
368            TouchEnter,
369            TouchEnd,
370            TouchCancel,
371            TouchStart,
372        };
373
374        pub use webapi::events::pointer::{
375            IPointerEvent,
376            PointerOverEvent,
377            PointerEnterEvent,
378            PointerDownEvent,
379            PointerMoveEvent,
380            PointerUpEvent,
381            PointerCancelEvent,
382            PointerOutEvent,
383            PointerLeaveEvent,
384            GotPointerCaptureEvent,
385            LostPointerCaptureEvent,
386            PointerLockChangeEvent,
387            PointerLockErrorEvent
388        };
389
390        pub use webapi::events::keyboard::{
391            IKeyboardEvent,
392            KeyPressEvent,
393            KeyDownEvent,
394            KeyUpEvent,
395
396            KeyboardLocation,
397            ModifierKey
398        };
399
400        pub use webapi::events::progress::{
401            IProgressEvent,
402            ProgressEvent,
403            LoadStartEvent,
404            LoadEndEvent,
405            ProgressLoadEvent,
406            ProgressAbortEvent,
407            ProgressErrorEvent
408        };
409
410        pub use webapi::events::socket::{
411            IMessageEvent,
412            SocketCloseEvent,
413            SocketErrorEvent,
414            SocketOpenEvent,
415            SocketMessageEvent,
416            SocketMessageData
417        };
418
419        pub use webapi::events::history::{
420            HashChangeEvent,
421            PopStateEvent
422        };
423
424        pub use webapi::events::dom::{
425            ChangeEvent,
426            ResourceLoadEvent,
427            ResourceAbortEvent,
428            ResourceErrorEvent,
429            ResizeEvent,
430            ScrollEvent,
431            InputEvent,
432            ReadyStateChangeEvent,
433            SubmitEvent,
434            SelectionChangeEvent
435        };
436
437        pub use webapi::events::focus::{
438            IFocusEvent,
439            FocusEvent,
440            BlurEvent
441        };
442
443        pub use webapi::events::gamepad::{
444            IGamepadEvent,
445            GamepadConnectedEvent,
446            GamepadDisconnectedEvent,
447        };
448
449        pub use webapi::events::drag::{
450            IDragEvent,
451            DragRelatedEvent,
452            DragEvent,
453            DragStartEvent,
454            DragEndEvent,
455            DragEnterEvent,
456            DragLeaveEvent,
457            DragOverEvent,
458            DragExitEvent,
459            DragDropEvent,
460            DataTransfer,
461            EffectAllowed,
462            DropEffect,
463            DataTransferItemList,
464            DataTransferItem,
465            DataTransferItemKind,
466        };
467
468        pub use webapi::events::slot::SlotChangeEvent;
469    }
470
471    #[cfg(feature = "experimental_features_which_may_break_on_minor_version_bumps")]
472    /// APIs related to MIDI.
473    pub mod midi {
474        pub use webapi::midi::{
475            MidiOptions,
476            MidiAccess,
477            MidiPort,
478            MidiInput,
479            MidiOutput,
480            IMidiPort
481        };
482    }
483}
484
485/// A module containing stable counterparts to currently
486/// unstable Rust features.
487pub mod unstable {
488    pub use webcore::try_from::{
489        TryFrom,
490        TryInto
491    };
492
493    pub use webcore::void::Void;
494}
495
496/// A module containing reexports of all of our interface traits.
497///
498/// You should **only** import its contents through a wildcard, e.g.: `use stdweb::traits::*`.
499pub mod traits {
500    #[doc(hidden)]
501    pub use super::web::{
502        // Real interfaces.
503        IEventTarget,
504        INode,
505        IElement,
506        IHtmlElement,
507        IBlob,
508
509        // Mixins.
510        IWindowOrWorker,
511        IParentNode,
512        INonElementParentNode,
513        IChildNode,
514        ISlotable,
515    };
516
517    #[doc(hidden)]
518    pub use super::web::error::{
519        IDomException,
520        IError
521    };
522
523    #[doc(hidden)]
524    pub use super::web::event::{
525        IEvent,
526        IUiEvent,
527        IMouseEvent,
528        IPointerEvent,
529        IKeyboardEvent,
530        IProgressEvent,
531        IMessageEvent,
532        IFocusEvent,
533        IDragEvent,
534        ITouchEvent,
535    };
536
537    #[cfg(feature = "experimental_features_which_may_break_on_minor_version_bumps")]
538    #[doc(hidden)]
539    pub use super::web::midi::IMidiPort;
540}
541
542#[doc(hidden)]
543pub mod private {
544    #[cfg(all(target_arch = "wasm32", target_vendor = "unknown", target_os = "unknown", not(cargo_web)))]
545    pub extern crate wasm_bindgen;
546
547    #[cfg(all(target_arch = "wasm32", target_vendor = "unknown", target_os = "unknown", not(cargo_web)))]
548    pub use webcore::ffi::get_module;
549
550    pub use webcore::ffi::exports::*;
551    pub use webcore::serialization::{
552        JsSerialize,
553        JsSerializeOwned,
554        SerializedValue
555    };
556
557    pub use webcore::newtype::{
558        IntoNewtype,
559        Newtype
560    };
561
562    #[cfg(feature = "serde")]
563    pub use ecosystem::serde::{
564        to_value,
565        from_value
566    };
567
568    pub use webcore::global_arena::ArenaRestorePoint;
569    pub use webcore::global_arena::serialize_value;
570
571    #[cfg(all(target_arch = "wasm32", target_vendor = "unknown", target_os = "unknown", cargo_web))]
572    pub use stdweb_internal_macros::wasm32_unknown_unknown_js_attr as js_attr;
573    #[cfg(all(target_arch = "wasm32", target_vendor = "unknown", target_os = "unknown", cargo_web))]
574    pub use stdweb_internal_macros::wasm32_unknown_unknown_js_no_return_attr as js_no_return_attr;
575    #[cfg(all(target_arch = "wasm32", target_vendor = "unknown", target_os = "unknown", cargo_web))]
576    pub use stdweb_internal_macros::wasm32_unknown_unknown_js_raw_attr as js_raw_attr;
577
578    #[cfg(all(target_arch = "wasm32", target_vendor = "unknown", target_os = "unknown", not(cargo_web)))]
579    pub use stdweb_internal_macros::wasm_bindgen_js_attr as js_attr;
580    #[cfg(all(target_arch = "wasm32", target_vendor = "unknown", target_os = "unknown", not(cargo_web)))]
581    pub use stdweb_internal_macros::wasm_bindgen_js_no_return_attr as js_no_return_attr;
582    #[cfg(all(target_arch = "wasm32", target_vendor = "unknown", target_os = "unknown", not(cargo_web)))]
583    pub use stdweb_internal_macros::wasm_bindgen_js_raw_attr as js_raw_attr;
584
585    #[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
586    pub use stdweb_internal_macros::emscripten_js_attr as js_attr;
587    #[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
588    pub use stdweb_internal_macros::emscripten_js_no_return_attr as js_no_return_attr;
589    #[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
590    pub use stdweb_internal_macros::emscripten_js_raw_attr as js_raw_attr;
591
592    // This is to prevent an unused_mut warnings in macros, because an `allow` doesn't work apparently?
593    #[allow(dead_code)]
594    #[inline(always)]
595    pub fn noop< T >( _: &mut T ) {}
596
597    // TODO: Remove this.
598    #[derive(Debug)]
599    pub struct TODO;
600
601    impl std::fmt::Display for TODO {
602        fn fmt( &self, _: &mut std::fmt::Formatter ) -> Result< (), std::fmt::Error > {
603            unreachable!();
604        }
605    }
606
607    impl std::error::Error for TODO {
608        fn description( &self ) -> &str {
609            unreachable!();
610        }
611    }
612
613    pub use webcore::value::ConversionError;
614}