stdweb-0.4.20/.gitignore010064400017500001750000000001151331624470200132750ustar0000000000000000target Cargo.lock node_modules .cache examples/hasher-parcel/dist *.swp rls stdweb-0.4.20/.travis.yml010064400017500001750000000012121347032716600134240ustar0000000000000000language: rust dist: trusty sudo: false custom: test: &test stage: test cache: cargo: true directories: - /home/travis/.local/share/cargo-web/emscripten addons: chrome: stable script: - nvm install 9 - ./ci/install_cargo_web.sh - ./ci/install_wasm_bindgen.sh - ./ci/install_wasm_pack.sh - ./ci/run_tests.sh jobs: include: - <<: *test os: linux rust: nightly - <<: *test os: linux rust: stable - <<: *test os: linux rust: beta - <<: *test os: linux rust: 1.33.0 env: SKIP_RUNTIME_COMPATIBILITY_CHECK=1 stdweb-0.4.20/CONTRIBUTING.md010064400017500001750000000043741331624470200135510ustar0000000000000000Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. # Contributing to Web APIs 1. **When implementing properties and methods, follow the HTML spec** * A helpful resource for translating types from the HTML spec to Rust can be found in the `TypedArray objects` table [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray#TypedArray_objects) * Try to stay as close as possible to the original JS name while maintaining Rust naming conventions 2. **You can run `stdweb`'s tests with `cargo web test --features web_test`** This will run them under headless Chromium 3. **For concrete Javascript types, define a struct as an `instance_of` the concrete Js type** eg: ```rust #[derive(Clone, Debug, Eq, PartialEq, ReferenceType)] #[reference(instance_of = "CanvasGradient")] pub struct CanvasGradient(Reference); ``` 4. **Make sure to document the struct according to the documentation in MDN and provide a link** eg: ```rust /// The CanvasGradient struct represents an opaque object describing a gradient. /// It is returned by the methods CanvasRenderingContext2D.createLinearGradient() or /// CanvasRenderingContext2D.createRadialGradient(). /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/CanvasGradient) ``` Remember these are Rust docs so certain keywords such as `DOMString` and `Interface` need to be "translated" into Rust equivalents eg: `DOMString` -> `String`/`Enum` (whichever is more appropriate) `Interface` -> `trait` Also add a comment linking the actual HTML spec for that particular object eg: `// https://html.spec.whatwg.org/#canvasgradient` 5. **For functions that can't be overloaded properly with traits, define multiple functions with a suffix to specify their use** Try to find one "general" or "basic" function that can take the original non-suffixed name 6. **You can export structs and enums by adding them to [lib.rs](https://github.com/koute/stdweb/blob/master/src/lib.rs)** stdweb-0.4.20/Cargo.toml.orig010064400017500001750000000037631354667000100142100ustar0000000000000000[package] name = "stdweb" version = "0.4.20" authors = ["Jan Bujak "] repository = "https://github.com/koute/stdweb" homepage = "https://github.com/koute/stdweb" documentation = "https://docs.rs/stdweb/*/stdweb/" license = "MIT/Apache-2.0" readme = "README.md" keywords = ["web", "asmjs", "webasm", "javascript"] categories = ["api-bindings", "gui", "web-programming"] description = "A standard library for the client-side Web" build = "build.rs" [dependencies] discard = "1.0.3" serde = { version = "1", optional = true } serde_json = { version = "1", optional = true } futures-core-preview = { version = "0.3.0-alpha.15", optional = true } futures-channel-preview = { version = "0.3.0-alpha.15", optional = true } futures-util-preview = { version = "0.3.0-alpha.15", optional = true } futures-executor-preview = { version = "0.3.0-alpha.15", optional = true } stdweb-derive = { version = "= 0.5.3", path = "stdweb-derive" } stdweb-internal-macros = { version = "= 0.2.9", path = "stdweb-internal-macros" } stdweb-internal-runtime = { version = "0.1", path = "stdweb-internal-runtime" } [target.'cfg(all(target_arch = "wasm32", target_vendor = "unknown", target_os = "unknown", not(cargo_web)))'.dependencies] wasm-bindgen = { version = "0.2" } [dev-dependencies] serde_json = "1" serde_derive = "1" [target.'cfg(all(target_arch = "wasm32", target_vendor = "unknown", target_os = "unknown", not(cargo_web)))'.dev-dependencies] wasm-bindgen-test = "0.2" stdweb-internal-test-macro = { version = "0.1", path = "stdweb-internal-test-macro" } [build-dependencies] rustc_version = "0.2" [features] default = ["serde", "serde_json"] nightly = [] web_test = [] futures-support = ["futures-core-preview", "futures-channel-preview", "futures-util-preview", "futures-executor-preview"] experimental_features_which_may_break_on_minor_version_bumps = ["futures-support"] "docs-rs" = [] [package.metadata.docs.rs] features = ["serde", "serde_json", "futures-support", "docs-rs"] all-features = false no-default-features = true stdweb-0.4.20/Cargo.toml0000644000000052140000000000000104460ustar00# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're # editing this file be aware that the upstream Cargo.toml # will likely look very different (and much more reasonable) [package] name = "stdweb" version = "0.4.20" authors = ["Jan Bujak "] build = "build.rs" description = "A standard library for the client-side Web" homepage = "https://github.com/koute/stdweb" documentation = "https://docs.rs/stdweb/*/stdweb/" readme = "README.md" keywords = ["web", "asmjs", "webasm", "javascript"] categories = ["api-bindings", "gui", "web-programming"] license = "MIT/Apache-2.0" repository = "https://github.com/koute/stdweb" [package.metadata.docs.rs] all-features = false features = ["serde", "serde_json", "futures-support", "docs-rs"] no-default-features = true [dependencies.discard] version = "1.0.3" [dependencies.futures-channel-preview] version = "0.3.0-alpha.15" optional = true [dependencies.futures-core-preview] version = "0.3.0-alpha.15" optional = true [dependencies.futures-executor-preview] version = "0.3.0-alpha.15" optional = true [dependencies.futures-util-preview] version = "0.3.0-alpha.15" optional = true [dependencies.serde] version = "1" optional = true [dependencies.serde_json] version = "1" optional = true [dependencies.stdweb-derive] version = "= 0.5.3" [dependencies.stdweb-internal-macros] version = "= 0.2.9" [dependencies.stdweb-internal-runtime] version = "0.1" [dev-dependencies.serde_derive] version = "1" [dev-dependencies.serde_json] version = "1" [build-dependencies.rustc_version] version = "0.2" [features] default = ["serde", "serde_json"] docs-rs = [] experimental_features_which_may_break_on_minor_version_bumps = ["futures-support"] futures-support = ["futures-core-preview", "futures-channel-preview", "futures-util-preview", "futures-executor-preview"] nightly = [] web_test = [] [target."cfg(all(target_arch = \"wasm32\", target_vendor = \"unknown\", target_os = \"unknown\", not(cargo_web)))".dependencies.wasm-bindgen] version = "0.2" [target."cfg(all(target_arch = \"wasm32\", target_vendor = \"unknown\", target_os = \"unknown\", not(cargo_web)))".dev-dependencies.stdweb-internal-test-macro] version = "0.1" [target."cfg(all(target_arch = \"wasm32\", target_vendor = \"unknown\", target_os = \"unknown\", not(cargo_web)))".dev-dependencies.wasm-bindgen-test] version = "0.2" stdweb-0.4.20/LICENSE-APACHE010064400017500001750000000251151307711256600132460ustar0000000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright 2017 Jan Bujak Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. stdweb-0.4.20/LICENSE-MIT010064400017500001750000000020351307711256600127520ustar0000000000000000Copyright (c) 2017 Jan Bujak Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. stdweb-0.4.20/README.md010064400017500001750000000512221354770247400126040ustar0000000000000000

[![Build Status](https://api.travis-ci.org/koute/stdweb.svg)](https://travis-ci.org/koute/stdweb) [![Join the chat at https://gitter.im/stdweb-rs/stdweb](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/stdweb-rs/stdweb?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) # A standard library for the client-side Web [![Documentation](https://docs.rs/stdweb/badge.svg)](https://docs.rs/stdweb/*/stdweb/) The goal of this crate is to provide Rust bindings to the Web APIs and to allow a high degree of interoperability between Rust and JavaScript. ## Donate [![Become a patron](https://koute.github.io/img/become_a_patron_button.png)](https://www.patreon.com/koute) ## Patrons This software was brought to you thanks to these wonderful people: * Embark Studios * Joe Narvaez * Eduard Knyshov * Anselm Eickhoff * Johan Andersson * Stephen Sugden * is8ac Thank you! ## Examples You can directly embed JavaScript code into Rust: ```rust let message = "Hello, 世界!"; let result = js! { alert( @{message} ); return 2 + 2 * 2; }; println!( "2 + 2 * 2 = {:?}", result ); ``` Closures are also supported: ```rust let print_hello = |name: String| { println!( "Hello, {}!", name ); }; js! { var print_hello = @{print_hello}; print_hello( "Bob" ); print_hello.drop(); // Necessary to clean up the closure on Rust's side. } ``` You can also pass arbitrary structures thanks to [serde]: ```rust #[derive(Serialize)] struct Person { name: String, age: i32 } js_serializable!( Person ); js! { var person = @{person}; console.log( person.name + " is " + person.age + " years old." ); }; ``` [serde]: https://serde.rs/ This crate also exposes a number of Web APIs, for example: ```rust let button = document().query_selector( "#hide-button" ).unwrap().unwrap(); button.add_event_listener( move |_: ClickEvent| { for anchor in document().query_selector_all( "#main a" ) { js!( @{anchor}.style = "display: none;"; ); } }); ``` Exposing Rust functions to JavaScript is supported too: ```rust #[js_export] fn hash( string: String ) -> String { let mut hasher = Sha1::new(); hasher.update( string.as_bytes() ); hasher.digest().to_string() } ``` Then you can do this from Node.js: ```js var hasher = require( "hasher.js" ); // Where `hasher.js` is generated from Rust code. console.log( hasher.hash( "Hello world!" ) ); ``` Or you can take the same `.js` file and use it in a web browser: ```html ``` If you're using [Parcel] you can also use our [experimental Parcel plugin]; first do this in your existing Parcel project: $ npm install --save parcel-plugin-cargo-web And then simply: ```js import hasher from "./hasher/Cargo.toml"; console.log( hasher.hash( "Hello world!" ) ); ``` [Parcel]: https://parceljs.org/ [experimental Parcel plugin]: https://github.com/koute/parcel-plugin-cargo-web ## Design goals * Expose a full suite of Web APIs as exposed by web browsers. * Try to follow the original JavaScript conventions and structure as much as possible, except in cases where doing otherwise results in a clearly superior design. * Be a building block from which higher level frameworks and libraries can be built. * Make it convenient and easy to embed JavaScript code directly into Rust and to marshal data between the two. * Integrate with the wider Rust ecosystem, e.g. support marshaling of structs which implement serde's Serializable. * Put Rust in the driver's seat where a non-trivial Web application can be written without touching JavaScript at all. * Allow Rust to take part in the upcoming WebAssembly (re)volution. * Make it possible to trivially create standalone libraries which are easily callable from JavaScript. ## Getting started Take a look at some of the examples: * `examples/minimal` - a totally minimal example which calls [alert] * `examples/todomvc` - a naively implemented [TodoMVC] application; shows how to call into the DOM * `examples/hasher` - shows how to export Rust functions to JavaScript and how to call them from a vanilla web browser environment or from Nodejs * `examples/hasher-parcel` - shows how to import and call exported Rust functions in a [Parcel] project * [`pinky-web`] - an NES emulator; you can play with the [precompiled version here](http://koute.github.io/pinky-web/) [The API documentation](https://docs.rs/stdweb/*/stdweb/) is also available for you to look at. [alert]: https://developer.mozilla.org/en-US/docs/Web/API/Window/alert [TodoMVC]: http://todomvc.com/ [`pinky-web`]: https://github.com/koute/pinky/tree/master/pinky-web ## Running the examples 1. Install [cargo-web]: $ cargo install -f cargo-web 3. Go into `examples/todomvc` and start the example using one of these commands: * Compile to [WebAssembly] using Rust's native WebAssembly backend: $ cargo web start --target=wasm32-unknown-unknown * Compile to [asm.js] using Emscripten: $ cargo web start --target=asmjs-unknown-emscripten * Compile to [WebAssembly] using Emscripten: $ cargo web start --target=wasm32-unknown-emscripten 4. Visit `http://localhost:8000` with your browser. For the `*-emscripten` targets `cargo-web` is not necessary, however the native `wasm32-unknown-unknown` which doesn't need Emscripten **requires** `cargo-web` to work! [cargo-web]: https://github.com/koute/cargo-web [asm.js]: https://en.wikipedia.org/wiki/Asm.js [WebAssembly]: https://en.wikipedia.org/wiki/WebAssembly ## Changelog * `stdweb 0.4.20` * Compatibility with the newest `wasm-bindgen` * New events: * `FullscreenChangeEvent` * `stdweb 0.4.19` * New methods: * `Document::fullscreen_enabled` * `Document::fullscreen_element` * `InputElement::selection_start` * `InputElement::selection_end` * `InputElement::set_selection_start` * `InputElement::set_selection_end` * `Object::to_iter` * `Window::confirm` * `&Array`s can now be converted to `Vec`s through `TryFrom` * The runtime should now be compatible with newer versions of Emscripten * The unstable `futures`-related APIs were updated to work with the latest nightlies * The `syn` dependency was updated to version 1 * `stdweb 0.4.18` * The `js!` macro can now be imported with an `use` * New events: * `BeforeUnloadEvent` * `UnloadEvent` * New methods: * `IBlob::slice` * `IBlob::slice_with_content_type` * `IWindowOrWorker::set_clearable_timeout` * `stdweb 0.4.17` * The unstable `futures`-related APIs were updated to work with the latest nightlies * `stdweb 0.4.16` * Initial `wasm-bindgen` compatibility; you can now use `stdweb` in projects using `wasm-bindgen` * Minimum supported Rust version is now 1.33.0 * Minimum required `cargo-web` version is now 0.6.24 * `stdweb 0.4.15` * The unstable `futures`-related APIs were updated to work with the latest nightlies * New types: * `FormData` * `FormDataEntry` * `MouseButtonsState` * New methods: * `Blob::new` * `stdweb 0.4.14` * The `js!` macro now generates slightly more efficient code if you're not returning anything from your JS snippet. This makes it unnecessary to add the `@(no_return)` annotation in the vast majority of cases. * New types: * `File` * `stdweb 0.4.13` * Fixed the procedural `js!` macro's whitespace handling * New types: * `ITouchEvent` * `Touch` * `TouchType` * New events: * `TouchEvent` * `TouchMove` * `TouchLeave` * `TouchEnter` * `TouchEnd` * `TouchCancel` * `TouchStart` * New methods: * `XmlHttpRequest::set_response_type` * `stdweb 0.4.12` * Improved diagnostics when trying to compile for the `wasm32-unknown-unknown` target without `cargo-web` * `stdweb 0.4.11` * The minimum required Rust version is now 1.30.1 * The minimum required `cargo-web` version is now 0.6.22 * `wasm32-unknown-unknown` is now officially supported on stable Rust * Debug builds on `wasm32-unknown-unknown` are now supported * The `js!` macro is now partially implemented using a procedural macro * String decoding/encoding is now a lot faster due to the use of native codec APIs * New methods: * `Document::import_node` * `IElement::slot` * `IElement::attach_shadow` * `IElement::shadow_root` * New types: * `ISlotable` * `ShadowRoot` * `ShadowRootMode` * `TemplateElement` * `SlotElement` * New events: * `SlotChangeEvent` * `IParentNode::query_selector` and `IParentNode::query_selector_all` now return a proper error type * `stdweb 0.4.10`, `stdweb-derive 0.5.1` * New methods: * `IElement::insert_adjacent_html` * `IElement::insert_html_before` * `IElement::insert_html_after` * `IElement::prepend_html` * `IElement::append_html` * `IElement::namespace_uri` * `IElement::closest` * `Document::create_element_ns` * `Window::get_selection` * New types: * `AbortError` * `SelectionType` * `Selection` * `Range` * The error messages for failed type conversions are now improved * The error type of failed conversions (when using `.try_into()`/`.try_from()`) is now convertible into a `TypeError` * Aggregate error types (like, e.g. `DrawImageError`) are now serializable through the `js!` macro * `TypeError` is now fixed (it was incorrectly treated as a `DOMException`) * `Number` can now be converted into `f64` with `.into()`/`.from()` * Added `Mut`, which is a new wrapper type for safely passing `FnMut` closures into the `js!` macro; it is optional for now, however the usage of this wrapper type **will be mandatory** in the future! * `FnMut` closures cannot be called recursively anymore * `#[derive(ReferenceType)]` now supports a limited subset of generic types * Asynchronous unit tests are now supported with a new `#[async_test]` attribute macro (nightly only) * Updated to `futures 0.3` (nightly only) * `stdweb 0.4.9`, `stdweb-derive 0.5.0` * Performance improvements; serialization through serde is now twice as fast * New events: * `ScrollEvent` * `DragRelatedEvent` * `DragEvent` * `DragStartEvent` * `DragEndEvent` * `DragEnterEvent` * `DragLeaveEvent` * `DragOverEvent` * `DragExitEvent` * `DragDropEvent` * New types: * `DataTransfer` * `EffectAllowed` * `DropEffect` * `DataTransferItemList` * `DataTransferItem` * `DataTransferItemKind` * `IDragEvent` * `Value`s can now be converted to `Option< Serde< T > >` with `try_into` * Deserialization of numbers through serde now works in the majority of cases allowing types other than `i32` and `f64` to be used * All of the events are now more strongly-typed * Previously in was possible to deserialize e.g. a `keyup` event as a `KeyDownEvent` since only the event's JS type was checked and both `keyup` and `keydown` share the same JS type (`KeyboardEvent`). From now on the `type` field of the event is also checked, so such conversions are not allowed anymore. * `0.4.8` * Fixed compilation on the newest nightly when targeting `wasm32-unknown-unknown` * New events: * `PointerLockChangeEvent` * `PointerLockErrorEvent` * `MouseWheelEvent` * New types: * `MouseWheelDeltaMode` * `XhrResponseType` * New methods: * `XmlHttpRequest::raw_response` * `Window::device_pixel_ratio` * `Document::pointer_lock_element` * `Document::exit_pointer_lock` * `0.4.7` * New events: * `AuxClickEvent` * `MouseEnterEvent` * `MouseLeaveEvent` * `ContextMenuEvent` * `SelectionChangeEvent` * New types: * `FileList` * `FileReaderReadyState` * Implement gamepad APIs: * `Gamepad` * `GamepadButton` * `GamepadButtonMapping` * `GamepadEvent` * Fixed `CanvasRenderingContext2d::clear_rect` * Fixed a leak when creating `TypedArray`s from `Vec`s and `ArrayBuffer`s. * `0.4.6` * Fix `docs.rs` again * New types: * `SubmitEvent` * `IChildNode` * Fix `CanvasElement::to_data_url` * `0.4.5` * New types: * `DocumentFragment` * `SelectElement` * `OptionElement` * `HtmlCollection` * New methods: * `Node::from_html` * `Value::is_null` * Expose enums: * `SocketMessageData` * `NodeType` * Update to `futures` 0.2 * `0.4.4` * Fix `docs.rs` (hopefully). * New methods: * `Location::origin` * `Location::protocol` * `Location::host` * `Location::hostname` * `Location::port` * `Location::pathname` * `Location::search` * These now return `SecurityError` in the error case: * `Location::hash` * `Location::href` * `0.4.3` * Objects which cannot be used as keys in a `WeakMap` should be supported now (e.g. some of the WebGL-related objects under Firefox) * New methods: * `Element::get_bounding_client_rect` * `Element::scroll_top` * `Element::scroll_left` * `Window::page_x_offset` * `Window::page_y_offset` * `NodeList::item` * `Document::body` * `Document::head` * `Document::title` * `Document::set_title` * `IMouseEvent::offset_x` * `IMouseEvent::offset_y` * Expose more canvas related types: * `CompositeOperation` * `LineCap` * `LineJoin` * `Repetition` * `TextAlign` * `TextBaseline` * Expose canvas related error types: `AddColorStopError`, `DrawImageError`, `GetImageDataError` * New events: * `MouseOverEvent` * `MouseOutEvent` * `PointerOverEvent` * `PointerEnterEvent` * `PointerDownEvent` * `PointerMoveEvent` * `PointerUpEvent` * `PointerCancelEvent` * `PointerOutEvent` * `PointerLeaveEvent` * `GotPointerCaptureEvent` * `LostPointerCaptureEvent` * New interface for pointer events: `IPointerEvent` * `0.4.2` * Fixed a leak when deserializing references * Fixed `CanvasRenderingContext2d::get_canvas` * Exposed `FillRule` and `SocketReadyState` * New attribute related methods added to `IElement` * New `Date` bindings * `0.4.1` * Support for newest nightly Rust on `wasm32-unknown-unknown` * Exposed `SocketBinaryType` enum * New canvas APIs: * Numerous new methods for `CanvasRenderingContext2d` * New types: `CanvasGradient`, `CanvasPattern`, `CanvasStyle`, `ImageData`, `TextMetrics` * New error types: `IndexSizeError`, `NotSupportedError`, `TypeError` * `0.4` * (breaking change) Removed `Array` and `Object` variants from `Value`; these are now treated as `Reference`s * (breaking change) The `Value` has an extra variant: `Symbol` * (breaking change) Removed: * `InputElement::set_kind` * `InputElement::files` * (breaking change) Renamed: * `KeydownEvent` -> `KeyDownEvent` * `KeyupEvent` -> `KeyUpEvent` * `KeypressEvent` -> `KeyPressEvent` * `ReadyState` -> `FileReaderReadyState` * `InputElement::value` -> `InputElement::raw_value` * `InputElement::set_value` -> `InputElement::set_raw_value` * (breaking change) `ArrayBuffer::new` now takes an `u64` argument * (breaking change) `InputElement::set_raw_value` now takes `&str` instead of `Into< Value >` * (breaking change) Changed return types: * Every method which returned `usize` now returns `u32` * `INode::remove_child` now returns `Node` in the `Ok` case * The following now return an `u64`: * `ArrayBuffer::len` * The following now return an `i32` instead of `f64`: * `IMouseEvent::client_x` * `IMouseEvent::client_y` * `IMouseEvent::movement_x` * `IMouseEvent::movement_y` * `IMouseEvent::screen_x` * `IMouseEvent::screen_y` * The following now return a `Result`: * `INode::insert_before` * `INode::replace_child` * `INode::clone_node` * `StringMap::insert` * `TokenList::add` * `TokenList::remove` * `Document::create_element` * `IEventTarget::dispatch_event` * `FileReader::read_as_text` * `FileReader::read_as_array_buffer` * `FileReader::read_as_text` * `History::replace_state` * `History::go` * `History::back` * `History::forward` * `Location::href` * `Location::hash` * `CanvasElement::to_data_url` * `CanvasElement::to_blob` * `ArrayBuffer::new` * `INode::base_uri` now returns a `String` instead of `Option< String >` * `InputElement::raw_value` now returns a `String` instead of `Value` * (breaking change) `INode::inner_text` was moved to `IHtmlElement::inner_text` * (breaking change) `Document::query_selector` and `Document::query_selector_all` were moved to `IParentNode` * (breaking change) `IElement::query_selector` and `IElement::query_selector_all` were moved to `IParentNode` * (breaking change) `Document::get_element_by_id` was moved to `INonElementParentNode` * (breaking change) A blanket impl for converting between arbitrary reference-like objects using `TryFrom`/`TryInto` has been removed * When building using a recent `cargo-web` it's not necessary to call `stdweb::initialize` nor `stdweb::event_loop` anymore * Support for `cdylib` crates on `wasm32-unknown-unknown` * New bindings: * `XmlHttpRequest` * `WebSocket` * `MutationObserver` * `History` * `TextAreaElement` * `CanvasElement` * New event types: * `MouseDownEvent` * `MouseUpEvent` * `MouseMoveEvent` * `PopStateEvent` * `ResizeEvent` * `ReadyStateChange` * `SocketCloseEvent` * `SocketErrorEvent` * `SocketOpenEvent` * `SocketMessageEvent` * Initial support for the Canvas APIs * New traits: `ReferenceType` and `InstanceOf` * Add `#[derive(ReferenceType)]` in `stdweb-derive` crate; it's now possible to define custom API bindings outside of `stdweb` * Add `#[js_export]` procedural attribute (`wasm32-unknown-unknown` only) * Add `DomException` and subtypes for passing around JavaScript exceptions * `IElement` now inherits from `INode` * Every interface now inherits from `ReferenceType` * Add `stdweb::traits` module to act as a prelude for `use`-ing all of our interface traits * Add `console!` macro * Most types now implement `PartialEq` and `Eq` * `0.3` * (breaking change) Deleted `ErrorEvent` methods * (breaking change) Renamed: * `LoadEvent` -> `ResourceLoadEvent` * `AbortEvent` -> `ResourceAbortEvent` * `ErrorEvent` -> `ResourceErrorEvent` * Add `UnsafeTypedArray` for zero cost slice passing to `js!` * Add `Once` for passing `FnOnce` closures to `js!` ## License Licensed under either of * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) at your option. Snippets of documentation which come from [Mozilla Developer Network] are covered under the [CC-BY-SA, version 2.5] or later. [Mozilla Developer Network]: https://developer.mozilla.org/en-US/ [CC-BY-SA, version 2.5]: https://developer.mozilla.org/en-US/docs/MDN/About#Copyrights_and_licenses ### Contributing See [CONTRIBUTING.md](https://github.com/koute/stdweb/blob/master/CONTRIBUTING.md) stdweb-0.4.20/Web.toml010064400017500001750000000000471347032716600127320ustar0000000000000000[cargo-web] minimum-version = "0.6.24" stdweb-0.4.20/build.rs010064400017500001750000000004401347032716600127620ustar0000000000000000extern crate rustc_version; use rustc_version::{version, version_meta, Channel}; fn main() { let mut current = version().unwrap(); current.pre = Vec::new(); if version_meta().unwrap().channel == Channel::Nightly { println!( "cargo:rustc-cfg=rust_nightly" ); } } stdweb-0.4.20/ci/install_cargo_web.sh010075500017500001750000000010301331624470200157120ustar0000000000000000#!/bin/bash set -euo pipefail IFS=$'\n\t' CARGO_WEB_RELEASE=$(curl -L -s -H 'Accept: application/json' https://github.com/koute/cargo-web/releases/latest) CARGO_WEB_VERSION=$(echo $CARGO_WEB_RELEASE | sed -e 's/.*"tag_name":"\([^"]*\)".*/\1/') CARGO_WEB_URL="https://github.com/koute/cargo-web/releases/download/$CARGO_WEB_VERSION/cargo-web-x86_64-unknown-linux-gnu.gz" echo "Downloading cargo-web from: $CARGO_WEB_URL" curl -L $CARGO_WEB_URL | gzip -d > cargo-web chmod +x cargo-web mkdir -p ~/.cargo/bin mv cargo-web ~/.cargo/bin stdweb-0.4.20/ci/install_wasm_bindgen.sh010075500017500001750000000013671347032716600164430ustar0000000000000000set -euo pipefail IFS=$'\n\t' WASM_BINDGEN_RELEASE=$(curl -L -s -H 'Accept: application/json' https://github.com/rustwasm/wasm-bindgen/releases/latest) WASM_BINDGEN_VERSION=$(echo $WASM_BINDGEN_RELEASE | sed -e 's/.*"tag_name":"\([^"]*\)".*/\1/') WASM_BINDGEN_URL="https://github.com/rustwasm/wasm-bindgen/releases/download/$WASM_BINDGEN_VERSION/wasm-bindgen-$WASM_BINDGEN_VERSION-x86_64-unknown-linux-musl.tar.gz" echo "Downloading wasm-bindgen from: $WASM_BINDGEN_URL" echo $WASM_BINDGEN_URL cd /tmp curl -L $WASM_BINDGEN_URL | tar zxf - export DIR="wasm-bindgen-$WASM_BINDGEN_VERSION-x86_64-unknown-linux-musl" mkdir -p ~/.cargo/bin mv "$DIR/wasm-bindgen" ~/.cargo/bin mv "$DIR/wasm-bindgen-test-runner" ~/.cargo/bin mv "$DIR/wasm2es6js" ~/.cargo/bin stdweb-0.4.20/ci/install_wasm_pack.sh010075500017500001750000000011651347032716600157470ustar0000000000000000set -euo pipefail IFS=$'\n\t' WASM_PACK_RELEASE=$(curl -L -s -H 'Accept: application/json' https://github.com/rustwasm/wasm-pack/releases/latest) WASM_PACK_VERSION=$(echo $WASM_PACK_RELEASE | sed -e 's/.*"tag_name":"\([^"]*\)".*/\1/') WASM_PACK_URL="https://github.com/rustwasm/wasm-pack/releases/download/$WASM_PACK_VERSION/wasm-pack-$WASM_PACK_VERSION-x86_64-unknown-linux-musl.tar.gz" echo "Downloading wasm-pack from: $WASM_PACK_URL" echo $WASM_PACK_URL cd /tmp curl -L $WASM_PACK_URL | tar zxf - export DIR="wasm-pack-$WASM_PACK_VERSION-x86_64-unknown-linux-musl" mkdir -p ~/.cargo/bin mv "$DIR/wasm-pack" ~/.cargo/bin stdweb-0.4.20/ci/run_tests.sh010075500017500001750000000063441350450675500143070ustar0000000000000000#!/bin/bash set -euo pipefail IFS=$'\n\t' export RUST_BACKTRACE=1 CARGO_WEB=${CARGO_WEB:-cargo-web} SKIP_RUNTIME_COMPATIBILITY_CHECK=${SKIP_RUNTIME_COMPATIBILITY_CHECK:-0} set +e echo "$(rustc --version)" | grep -q "nightly" if [ "$?" = "0" ]; then export IS_NIGHTLY=1 else export IS_NIGHTLY=0 fi set -e echo "Is Rust from nightly: $IS_NIGHTLY" pushd stdweb-internal-macros > /dev/null cargo test popd > /dev/null # echo "Testing for wasm32-unknown-unknown (wasm-bindgen)..." # wasm-pack test --headless --chrome -- --features web_test echo "Testing for asmjs-unknown-emscripten..." $CARGO_WEB test --features web_test --target=asmjs-unknown-emscripten pushd examples/todomvc > /dev/null $CARGO_WEB build --release --target=asmjs-unknown-emscripten popd > /dev/null echo "Testing for wasm32-unknown-emscripten..." $CARGO_WEB test --features web_test --target=wasm32-unknown-emscripten pushd examples/todomvc > /dev/null $CARGO_WEB build --release --target=wasm32-unknown-emscripten popd > /dev/null echo "Testing for wasm32-unknown-unknown..." $CARGO_WEB test --nodejs --target=wasm32-unknown-unknown pushd examples/todomvc > /dev/null $CARGO_WEB build --release --target=wasm32-unknown-unknown popd > /dev/null echo "Building standalone tests..." pushd standalone-tests > /dev/null $CARGO_WEB build --release --target=wasm32-unknown-unknown echo "Running standalone tests..." node target/wasm32-unknown-unknown/release/standalone-tests.js popd > /dev/null if [ "$SKIP_RUNTIME_COMPATIBILITY_CHECK" == "0" ]; then echo "Checking whenever the old version still works with the newest runtime..." if [ ! -d target/old-version ]; then git fetch origin refs/tags/0.4.9:refs/tags/0.4.9 pushd target > /dev/null git clone .. old-version popd > /dev/null fi pushd target/old-version > /dev/null git checkout 0.4.9 set +e grep -q 'path = "../../stdweb-internal-runtime"' Cargo.toml if [ "$?" = "0" ]; then ALREADY_PATCHED=1 else ALREADY_PATCHED=0 fi set -e if [ "$ALREADY_PATCHED" = "0" ]; then sed 's/path = "stdweb-internal-runtime"/path = "..\/..\/stdweb-internal-runtime"/' -i Cargo.toml # Sanity check to make sure the replacement was done successfully. grep -q 'path = "../../stdweb-internal-runtime"' Cargo.toml fi echo "Testing old version on asmjs-unknown-emscripten..." $CARGO_WEB test --features web_test --target=asmjs-unknown-emscripten echo "The runtime is compatible!" popd > /dev/null fi NIGHTLY_EXAMPLES=() STABLE_EXAMPLES=(canvas echo minimal todomvc webgl hasher) if [ "$IS_NIGHTLY" = "1" ]; then set +u EXAMPLES=( "${NIGHTLY_EXAMPLES[@]}" "${STABLE_EXAMPLES[@]}" ) set -u else EXAMPLES=( "${STABLE_EXAMPLES[@]}" ) fi for EXAMPLE in "${EXAMPLES[@]}"; do echo "Building example: $EXAMPLE" pushd examples/$EXAMPLE > /dev/null $CARGO_WEB build popd > /dev/null echo "" done echo "Trying to run the hasher example..." pushd examples/hasher > /dev/null node example.js popd > /dev/null if [ "$IS_NIGHTLY" = "1" ]; then echo "Trying to build with parcel..." pushd examples/hasher-parcel > /dev/null npm install $(npm bin)/parcel build index.html popd > /dev/null fi stdweb-0.4.20/info/logo.png010064400017500001750000000763001307711256600137250ustar0000000000000000PNG  IHDRs5 sBIT|d pHYs..,StEXtSoftwarewww.inkscape.org< IDATxo}}H$Jf/w8q A88>{<4%Dm\DͥWVuWyAƦ|ꪧN(@ ‰>@D @xI N Ku@ ^$ǽBEHMA^@ Wl=@Y'1@ _D :$nǸ2@ ԩO]xJZ 15si+8ElLN״A$@Q,f5m-#@ 4~o!Vb_~Hf`W;Me.ߟ;sٹMDiF (){U$Bu[EE`QMvg8W>AĽ>Pt ~d\8wf6>@ 4"-7B*~g[>WCK'h!PѾw=}lmE*'@ jz-:qcf X~=L4i˿^o ^om9‚F$e@  L܎lf hq1s%y[ +x !HT@ T*BiDj5FmG6+Bq]OTr<>|xܞ)Owبn!'b*H<~;F"#]zw@SuiXEܘucj Iy`(g؊]y&%\ H&9Օe Wmr;b7(p\5 ԫZ K8b6>peK"SE>']7/Dc,w9xGx' 0}gDezT0ep3,b U@ ^H*>]8`?)C4)'w PjZ Uo; l[~fht:wMw/}Oc2o_׼(X{ DA̻?pdD !W $8E,k+v Ƭ0 2W%7QRpFnp\>_mm$,? }?("Mlem2A]"|XǷ`9T0kUe |m[k˨'W" OVm3XW2x&&άci/+O 2^!*Ţ N,F%B h62D:p HEbK<ADBU`vڦ.E ^KRjzpX5D"ͭ(\F"VC{8.A.'/@ \+ "kqzЌnvN+)+z{ Fxv!'rpSH"V =0JW/u`PިId9@8+#8Q,mIV'$$m:t9# `$'tU~86VHR@ 'WMECFa}N-deI~SE+tZCf /|(a$bcFϠA$ҋ:/Ӌ5΋&8Y J5;t0iE QkTk: 'F9.DoJlsG y6ׂpvY #Iw%ॿ2Ypm٤٤$6?@ h5[;@xYxE$]MN 4smu׍@pWUW,crьxQ6"xꝮsLeij f9qxL4Z9_|ϊF׺աEM?ݭ.A]dhdi8z!\!,z#0;ۉaGӒ*)!//-/6CݚR 9pat-c<]ƪǨ']& y'ZbE]XK]KNtZO9`)Z\õ~r]oPaRfǫ'!/-/VamQ.:oҹjH57~.O|Xyv2\Nz`khU$G ZudgKo ۠8MC2l7fa;&O'JiX;:Mu7EQN Zuue:ڭk?lNT}3+aiˁc;~P;@P}ȔjG '"eWW'}qЄƹb =Askee5^qjvK)n3$O<;u5B'C ^NZRw2ޮ(>j=т.TE]?ͦjMk?C݈tK'2mn|jѴѫdd"/@/D/"'\N(dx#BzR-a(5nCd>l=(U*)&ϵ]_+o!#/2lYOSѶհ'cT[^ɤ( )Рi M)dPiI@Mqxz!}?LJIh|vɾx.> z,jLq@&ePs,X*qOtG+:֖; QNZ w`a~b!D$ `GM練;Yӱ aߣl^Ao*9.:O?[re惽&\:t'KӀH?\rg8E'{J@fǖ @N4\ԃ\Bm0iN^<ۈ sNqCڬvmm V ܙqwM\B5<9i+%ͿR2 ϝAWRfl#V.')-TEIoY'G"iܺd+=ǍաGP۱[c.I@ pQIdVvnFqAxr'E)kƕ2S)w^,]&t7f0}F B)Ёi3yyA9/\+)W+]Axj &qjDE<V!u+@ ԟJFVڒVIxx|:g;Yt;11jDžq;)0zKXwv^s䮵fgfZh'dUyWת>}¬T&Ol!N˝ݞ(2\Љ1E< 1= D]PO$Rcul]'@ .MuAm#kbcZg[h괫T'4R?iի}ۋ|e9nbi 7ᬃ -Q#][O|,`y=Oga s 3,:iZ6[ԁgq\;%\0n|xmzjsd &//M%oH}.MTW CE-PZw.u`yؚfiqj/%2I3WZn$:wY>B%4>Yi, %A-ǪY"->Ԥ۩Ĉ.p,J9hcT6v/be9@ #NݭtFNݑqm#`+Hӿ@ z]lۉ,c 8D2=.Ƽ,W.8چζޔ0٬ƕxzEdp{zݽAH{ȁp x!\%JJ+JZ$5*juA`=A0a;OWC3zW(kbU /x0aMjuahʺ1p^ϯ7kam' By%xzGg)N3N3,6& ˯-y9Ow^3 R9䲅(CGvbBD"R)8%M`íxl9aPa v(ͥ LAhUZP K whqaܔ1""f󿈣Sjl5V]#n1!Rޣ)pqV"MaeыRJ# yo+k=้GRX IU$ . !.D "M7,_R'_DGE|ĢOØ o QD2D])gpiĊvO+ w'Ok~p\"Q}L?SL{È{͏ͧ/$0ri*mz:[ IDATbh :\[*^=ڡ-)@S^?eA2pgœcDxWմm:I[:lN97VMsc} (`|B/RoovZp:^!( p8 Xp= E3]ftK,p`A'UQwj3TR\-!(Q =$ P ?“( R Y[^In#xnh g=e`c#'fq:ۉ|ooi$R~=TZeoh+Umhmo@h](]>ߣ/j1C%coWa}TPR,Uom;,XvǑ~do--/ $q@cq~́6^ك7<]({ <|>'`zz[jQЍm_ ϖ=ҹ|kxlPzqY U,.:W4Maq+o8]S-R-0 6"n\r .w';dlV &;0;+X[ !I'֬/Ůɪ66e0b(W^(r-ZlCȤXt 81yH ZEeh+dYSUZ"3C,>yJc cq3:^KP ) AXzW/wM$Ŗ#4n\6[ǝgݩʢ""BB+}NYT Ibqf*N3c^Bk. +"Ѕ8nU)c0uBsAjx-KC ㎢bs=eU($r =lfyܽS6HOP=.r #g; &)},S ǣJO*&8 vZ S*W۹񞝝Ž{055c^1;;q\r0ǞSi2SS.Ha*ۦ`=!|C&(ݨ DBD;pB^sS8=lqv087Տ6W%f'{es_Boi7*^<q=ottWGȇ({ٵk077']]]Ǽ)) 71D +Up#^?7Z)c05bF γ9xfgGml+OLUtes2Aba\^RMh:l#֭+7¡/? go*[M+':_wh) ;(\pX]>2KP?>R' `xȆ֞l𹣈(»DP[EyK0!hAw=NV׿] /JO?XS$ !"8C:Ƶkp]d2h^>Y #[ɤras~;\Y'G[Z /?tZ9;TTv!/͗_E˓ݸ;t9 x 7ӧP[+ !U>w#Mmu F'` oBiA&<Ν;q,,,7;"4Avqayy~)r2[Dlsx|pׇ?8c}_4l#Ŗ/6ysOØ{FɠâBYIYq|#`9pmE ~uԘ<*Y+W4Q V+ܝ@4v\ ^E=o ; ':ZW# "q\7Ժޒ,y 'NV 0BOO3!:::H$077w̫#atvv{7kooqώyuQPi 04*ڪC,w<mbS >3gp=g$L簸z FYN&0E+1^g3'9mQĝ:nLr))"r6v 5o gQ䓖X>V߫+#pO"f֏bw`h PuY CTTHE$Z CfPaVfV(xX]-u1`lZuB\>DQ,&WepR7fg7(zUDlîC{tvہti4U 2bݎH-zt҂o޼ EQ0{ -Q J&) 赪0ޭM'G"LoU=kDSX2H2XC$!琩o0o0 \oK34Ν|ns:YLNv޽Mœ^J%ϋe"_R)QQ I Z~ɷBoѢL+/᷿-lK@Q?9Ze5T+}Рpgx)CaȩX}dBNWq5_c=z(e ƃIg\V@4!"gq'm\91Y̥J~ߏT….o"/y*U{DJCoPh@oTAQzSCv< WE/t@"q/ /@\θ}zpųA%g0ڡvm1zX$)M0"BLJêWW.",BqPC$6Ecf ɘ-\9ouD tȫ Q I Q V^Q@-=LoɪC2׵?ZSA1 q?8g?+ZyQ?0ɚ[qϸgrX ԧؤLunTy 3zASZZ|.PE0b;F ^G~{^'I/Ũ٠NpJ6T!M#N!M#gϠah`47ood7JRF*?ցNFލmU_fgacc㸗BxEWT|q-R\gt4WVoFheV=ɲE=4MWW`KHerF9ilihHH+(*&fZr˰lJEe'! gHOE&dVhVdRCVǮ~OA{ct1ûo=,W[LU"g:v}cco{)BKRUQ.1ڦ*2Mj)>7jYS]CF򎷢SYnRHݦEs w>qT*TY*a6(a4(`2*a!-Q XY <^\8TNsX, bq1h^٢ɬFۘD*"/֨i*#akC[0k*rHčfJ˫]lz4XT6k}͗F&9;n? `SlNo; ME: zF:|ύβ9ܾ;t0P 7n<$, D8[u+JRK\ʝNQN9+{i.3&>Dx}l(-mg20 ۍ`0x<N 0́$$0??1(9 ~ӟ!nd,TE, L&A4z=v;f3x\޸WAqG2D6^`nD"0Mcfr !" :::@QTUQoƱ('X af͛AcCc6nl (4%=k^i0HoLrqkr( Ghs6o{[;MPi`4[*Qr9>@o YE$~e<^JeŐ`Ӄ!ttt@Tbvv+bzzfqk}+~A尸7nr՟k4R \.ror0D"o/B}}ddp˸vbl˗1:: FSRDQ~G9{,|͢9 q>>Ci OO`٠P(H${! +~|Gvy\ra A˲~q7[nh_J08KRq"+-U^[oη6 ^"].ܘ{8c6t;uHm'!3-]x,x$ߕ+`j  n?4dEWOs$,zY]ǽuն\O^\~߇~<>;]c8?|k_sڞ8'?6 wyG$9"l<) |.*f8|ᇸqt!^w?ߏclmm(|_ĭ[|K_+rHT N,G?X62e\x,TdY?ZmN'X evBO7[vHb7ooxկ~ r2]KΝ;կ~uĊ?uWI}7xhF.C4~7?7xa^ |~Z(UV. N^z I( wX$sRJ۩k_o¸N4XMif## ._AGqkMtQ-QeptVv~C"ejef"^p@GGrd2h4-GYaf?800LG\AgY?O}ppַh ^w?ߡ(?<""t:o~GGGv14 \*ydsr9FFF+_A___ENxz-|߀`B8=H$d2LNN_W's K$}>Ӻk?%oqs5l:*ʫlSq뺎B04ϵ[Hfd`7^U*ԡ˩ $ܾ8$ru7 CbfUjɠmb408pr>[ݬbP?d4ۋpaJ!"677C;Vg%L&>4__rVYg}{%]ݥH$p:8}t^v5aLMM千ƚ#A 8{lEq~`0 e_&玔:nll>-cfǥKյw#dׯ-\b`llIewt9l'W5"W`j\%ZbyQ\9(ѽ*\rF;S.;pN5 Mx!;ө?" `}"3?<WEWj"/³Y,](EA.wީj8{NQTQ˶rX5#e~dx뭷yޚn8ógU"V߿QoFsY|<~A.կb```ϻ0 j5&&&|_׊z)?`h *v?kŢ:65j!zFr=$EFBV5ΏwNu!5T&өDžxwfQ؈cյL"*CԻu2m[Wx ,Z c +dxZ+b~~{ύCV|I4a6'd4qid2]iG%LQ`4^7,F86Ε44\2ME2RONaϓy/J3) 0;ep4 RcnΌjєUG."\iŒo4Hht GkQh`r)xb=TX|p{ad2^zŪ<\r<\.WՖ  |rE<~_J%FFFuD~W]}ZuB|H$EOOOܹS~ qH5h<%c _,?5z G23>!'`P@^c`0dݱɤq|X47KCFRqay?@4X\DQ?z.b8'|r:,yT\.kv-ӕOʔJ=|2ijg*,n޼ J$YŚD")x8dxJ[F,Q z*aRìf0Uru#p.&NYc pfcAܼB CVCA+a{CWܒ)$:u>4V;NCs[@"=n*݈eV4Mh~~YaZa2 u}݊Yt>3T$sssP)3s=,//}|RT JeZhkkh뀷e/y g5PJ|{).|UABs R,UZVQ@]-hM,h\J{vn5lZJd;}4u5r#a%'j?~\yfv\r佱X(]A,AիW+v'G bQ&qmLcݙ/ryK"%Q7url'mRpA(/o @/F- 4vl'l%Er}Z^3+콳|:'U,  C9A=0YE[-𸶮"39T㕭hꋯa :12Ɖuwгc4T$,l ٻKeJ5&9Ei}3 Cwj,{O/{BVz-011QSU.q.2.\߿8N1tkN;T*tXšC^\*EvK8@^K+~pn4Bdoep`n}KmUGkwۭuG34Ξ媚SSC5<_.S5 ]w9kXX{38l\.XHhӊg˶UXʼn'77uU A*j+RcVeYŋ%Qq yKܻwOSl$"Z%H$bN$,v&gC}xn_'<#0٭G%1(w] !ߜ>v86t8X)mQ :}YHj53nxZģr'+߉3{l6pW___LursrХRwj~ÁGn{)dMNUt-z-E7E))Vnm:qpub=,,u^$Yr{F6Tvc{!.1[,geTw!wƏck#;R)ۺ{7{V4fEG+W(.2{=f?,{ydPhm,޽{(JxgZa!0<׼NCItUoK+k _ uS3ӘS ,B(w/$d%BY YqpcS8;]g30 'O,j~hϸ(]iZqtP, |x7dv]n;uIc`n]2{Kh,RvޥR+/)a_AV `*rY1!*̭na,Ξ=Ącwe k;b䤮DIL//|\wrkn{CIgyd_$5f- C̉!mQi Ǐ Ihna1Ic{\ca17 fd*)bn[!Lne/ٳshM#Ia^z: 3eyc7늰qܗ/_n{wq{&;pXM:F:jZ~.6 i\_jR]nƘB(J]=0ww.tV{{p6ԁ6p$H4MB[,"R;3C up̙?쳍͛71>>ސw?!! LٳtLNN*FdY/K]A8}tf1<666@ 4%Ҹ7~rhL*B9cy_]o>fZ3 WOWܹƃbԠz$b9HS3uj&rXk;'fl^o &&&TO>1LZL&;wF`P*B$|hX~?~1.\p9:Ν;x{2[oV^\p+++j[ xuǺ/4+ʗw)p[wVbE=հp⠜_kG\?`VKe#\|` QiLOOcbbBJmeK/~햦 ;wSl$ͩStА62ݛ41F%&zo.i}^ l]kcp@sk]"I2quQ t2_hPNt4K-Vy{;lxR37U\.ѣG50 ?qㆢz#Pf:qU~)A׾v 5B[TP.u W}?-}!77M˻lvbԩS ?WM/_x<$P(`nnNQL&~ j[oX'pp:!;Lvo୷ުEHDqz^#G_zS"L4>EG}H$??d=۷o. o^c5_YZ/pww8C}6 :3{nͤ xv\TNE/;w$"~mx0HEz J _pS;jqՕ+Wjr֢(ڵkvm v]=XݨFxc_,@$$ D"4طof^\իW155~p:mO;zF-⛡.FFF4l0~>}Y|[j8|+_'5}333ۿ[|ƩS IRMڣj)}^q1?OtMQ'?v.Cv;k°{~hbxF:?-.!(6z17?1ԽRV!||{[x<ӣ[bxz:ƕ+Wjn_\\իWq^F5zR޼y$oi`zzZpbW_űc~a0>>QϫEQD6E4E,C>o,J?7ꫯbp\0LyrY($I>ٟ5ԄiA|o}[MUѷVgϞntW_ٳg[n3LZ8z(&''dL~EOP.!xÇ駟߱ ۍ׾ґHY^f!1Ltk$`kf k[&RY^@1udXp̰ZLY`YX'2ĊrEBPF Ok)]W1V63"Wˆ}#VX~& ˘R~_׿5<<8C>G($I}ka61>>'xw1;;3yLC,brrW>.]Rt֪xsm/"5#B4N:w}W޽{#Gt70 l6^}Ub1|li8w^xL&]>{q?!J>ܻwo#_.qMܼyshΟ?aI;YJ J2ţ̆SQ')7 ^qՕ8.玶[kXZ6S-ybnguU b<"‘L͎S阆8ztPqFٜζЅ##;T4kfa]X tl %2$Irf%IB,C"@2D6(p8ػw/;R Q0 * h%[](DQ,.."CE\.add. 4MלyG}apy0 sNR( m_-Jx"QeX^^ɓ'V*0 B=zd2r ߏݻwCe*ʁ߂$IeKKKRex0<<|'k\ͬx̄ Ql7D/m w/~^:1бcYY⍐l04~+vX:ME k,-N k<1@@<XxU\|+sa}D\>'#}p]9i4Ju*0=}PM%4cZi(Z_Nӫ*fL$ (*.ES/`6P>=B4oO*)K FUEI7[Y@3Qpg>hB9ള8y_4 T ߽Fd\>ծ2wmZNHFR(|";]EbFs$sYgh~Y*Dw S[= l,UvT$ܞ6&^9Tũ(X~`|@ xT !)0psPR3Px(tgb-1!N߫ ʛA+UDhlȅ]0 T~X~ˡQ%Q(pfu .~i>d^ߓ,-RTDbk1erYLT_?I8,Q+2fn5h;lf`u&_Kiھ6JY`βGD  /&|#Sn)xUEQB<Պk:T C<{p('R%,.uyTFC-$ce]zT4ت@ Ӗz2aCY$Yƍ.|r Lx2J4CNqqZ%:G /X"axms)$ { 1]> x`}\+\FQk8hǞ'7cؘO>Y1=B^cEցl+VD,]u ΣeQy\7(IqmuƎ9Q{)TX-'Yê2~X(LLT*RC}b԰u*ni,@xhIepָv9#q۵ ‰D7() 8{$سsah-~\W:sⲛU+"Y*_܋#nbh;Y2<^;xpz:UD\id,ɘӹ"68uZuMᕩ rDv*VVw닫Y+v}Y+ʈerrE|bYsk94~b#4QX e nMY9N zOg3xYq2NޭZ(4aD,˘Y֥Ll;-,;m0sO_ia0!tD] g3a&/%<`-G:\KaOf[$XK1X'2tDӞԡD4zB$)L{;T9&Ucv-őϴ yp¬Ru5$Y̪>;t찮S*m %IFE @YNYJeT.Al=b [Ø(*h;&`dێl݇ :\ceW!UHE2(9F cgH2=+n /U7 ivR4M᳛Hpq Q![łx [SujkyiK7h,CS`LefĀǷ1l(Iѣxo d{JHrE +Y 1Иow3mE䋕-B%;IP>uk}Bڭ|_]#>{]+ 7@ <=t$ϕJu 8)Bt9`6zCK ,оEY &A?:"3i!H5hDQp-;Ik!_-2fCqXEqy#O'e蟓Ԣ\0sf:$!OeJy6ʑ ۤ f1 F.]D>SE$B.f}2K,|yC2$I1n™q&X9,`Z/TchP`blΉWD|BY T*EBEQ}cv U17ԕu z@WJxz}N xF(~y=z!22<2|#n@!.C^Ad7ESpXx|. n.'װL@Q\. \/uyxPrRBa,|y/I2ʢQZ/\D $T*mIl9rcC^4h>uC#<ʲ,#(""ˡmr\kt1+ ]ּ᱂e͠( &3ͬ3P4~6nc-,lN A/:&ꭲ(kF:PYᰚa6D%6MkU& ~> ^+.N'\G(Z| a)Q8<mz^7X!{8W&I2s~%^lX93ׂ㝸iiiDTjHf#D߈Ynasi LJ HVa>"@ t'M}88V}=N lfܮA'>+<( llVSxD!=0tb֟ww"b21kWI| @ ig:Fݪ+ 6aƇDۄ) x̳տ@ЉS#5߉'vJ8QwX8c आj4UEIՂ<2k=6 e Aϋz,c䈳]yaB&SRZ74]~=K|F=-C E= y]r;oɉ]O2)oq viS'AFqZ0 ;d6+l×Es,@F2_KSmXjAWyQfv i׋Nf(Ll eJ e[$IFœpIxbIR,<_+ϒ(CjH|Ӣ5HZEVڎxO:tk3-KD@ =-aErԜJ,@LNo@di#]l-j5S YR(I OOz:gmgPŻ_+|;@TMwA.Oe,<{X|oY[hm*Wﮭ5'>E;-K2n]R~,ɸ{kH@zz;Uc66(eɗqjޭ}̩\Ә_Bk =rmpb>݊] X#ugW f8@5zZԧqN5wspww[6ZB>PΝ%*, YY"!2hbx BwCXn I2xd,X)?<,gȦJȤ ȦJگk~ @ M[x ITD(x&8{,8Y̖ܹ=WH^ziTͮuY+խtc* dddr%H E?ƞCÆ B#(*,fi_p\ m\S#. 8SHH8G A:'㓃kܧJ`G 814kh2ug v7ذ{؉d' X]I! -VPZ{"|S9+(JXZbi- ՌCNvfy:rYD4j(T7ftO7BxeBX\w:-coe{X I2iQw9X9܏-s;^+~exw1/ά!,6:'V!&5QuMQ]n؆W{-p}x=mzӻ x[ED@  $ V3^:5~MS)Vvp=p6`z@ 7nǪ)`.>ɢޮi9췃љfh hf6c8sn7@vX>&@؉z 9qg1Us̡M7 ah@`}2x=squ z}r}CCu(žq?~;fC]0Y٩ //wf3#>HScMTgO n:Nl3ux`CgùS#-xzeřg`Xִv t 4@T,#!q=ߍani}Omo_&'SCOߍbarmۏQSG_7q2x{|6>=FT$$[Soﶴ%{X;߼Ƴ53d@~ùӣX7luFЉ:@ ԁzqjؾVa rf:b4Mс؛9rl3`qf1{Ǵwf3iGwOA V[,&;3GQ##nbkJ z02ժ܌ ?3n~3}p60#e>vW<&΄3Gt(m D{p`O%f gGn6)?U' @|w#Ǯ G!0:Ǒ3@$e`a DQgÁq氛F7-U\85^$ɘ!۱oo$=@ Y.^]Aqk. ϟU8@ Od/@QA7ٙL4N"N ;Se !vla}@ D @!;@ ;"@ C N 9q}PIENDB`stdweb-0.4.20/src/ecosystem/mod.rs010064400017500001750000000001351323466772300152510ustar0000000000000000#[cfg(feature = "serde")] pub mod serde; #[cfg(feature = "serde_json")] pub mod serde_json; stdweb-0.4.20/src/ecosystem/serde.rs010064400017500001750000001504011350450674000155650ustar0000000000000000// To give credit where it is due - a significant chunk of code // in this file was borrowed from `serde_json`. use std::fmt; use std::error; use std::collections::BTreeMap; use std::vec; use serde_crate::ser::{self, Serialize}; use serde_crate::de::{self, Deserialize, Visitor}; use serde_crate::de::IntoDeserializer; use webcore::value::{ self, Undefined, Null, Value }; use webcore::serialization::{ JsSerialize, SerializedValue }; use webcore::number::{self, Number, Storage, get_storage}; use webcore::try_from::{TryInto, TryFrom}; use webcore::instance_of::InstanceOf; use webcore::array::Array; use webcore::object::Object; use webcore::global_arena; impl Serialize for Undefined { #[inline] fn serialize< S: ser::Serializer >( &self, serializer: S ) -> Result< S::Ok, S::Error > { serializer.serialize_unit_struct( "undefined" ) } } impl< 'de > Deserialize< 'de > for Undefined { #[inline] fn deserialize< D: de::Deserializer< 'de > >( deserializer: D ) -> Result< Self, D::Error > { struct UndefinedVisitor; impl< 'de > Visitor< 'de > for UndefinedVisitor { type Value = Undefined; fn expecting( &self, formatter: &mut fmt::Formatter ) -> fmt::Result { formatter.write_str( "undefined" ) } fn visit_unit< E: de::Error >( self ) -> Result< Self::Value, E > { Ok( Undefined ) } } deserializer.deserialize_unit_struct( "undefined", UndefinedVisitor ) } } impl Serialize for Null { #[inline] fn serialize< S: ser::Serializer >( &self, serializer: S ) -> Result< S::Ok, S::Error > { serializer.serialize_unit_struct( "null" ) } } impl< 'de > Deserialize< 'de > for Null { #[inline] fn deserialize< D: de::Deserializer< 'de > >( deserializer: D ) -> Result< Self, D::Error > { struct NullVisitor; impl< 'de > Visitor< 'de > for NullVisitor { type Value = Null; fn expecting( &self, formatter: &mut fmt::Formatter ) -> fmt::Result { formatter.write_str( "null" ) } fn visit_unit< E: de::Error >( self ) -> Result< Self::Value, E > { Ok( Null ) } } deserializer.deserialize_unit_struct( "null", NullVisitor ) } } impl Serialize for Number { #[inline] fn serialize< S: ser::Serializer >( &self, serializer: S ) -> Result< S::Ok, S::Error > { match *get_storage( self ) { Storage::I32( value ) => serializer.serialize_i32( value ), Storage::F64( value ) => serializer.serialize_f64( value ) } } } impl< 'de > Deserialize< 'de > for Number { #[inline] fn deserialize< D: de::Deserializer< 'de > >( deserializer: D ) -> Result< Self, D::Error > { struct NumberVisitor; impl< 'de > Visitor< 'de > for NumberVisitor { type Value = Number; fn expecting( &self, formatter: &mut fmt::Formatter ) -> fmt::Result { formatter.write_str( "a number" ) } fn visit_i8< E: de::Error >( self, value: i8 ) -> Result< Self::Value, E > { Ok( value.into() ) } fn visit_i16< E: de::Error >( self, value: i16 ) -> Result< Self::Value, E > { Ok( value.into() ) } fn visit_i32< E: de::Error >( self, value: i32 ) -> Result< Self::Value, E > { Ok( value.into() ) } fn visit_i64< E: de::Error >( self, value: i64 ) -> Result< Self::Value, E > { value.try_into().map_err( E::custom ) } fn visit_u8< E: de::Error >( self, value: u8 ) -> Result< Self::Value, E > { Ok( value.into() ) } fn visit_u16< E: de::Error >( self, value: u16 ) -> Result< Self::Value, E > { Ok( value.into() ) } fn visit_u32< E: de::Error >( self, value: u32 ) -> Result< Self::Value, E > { Ok( value.into() ) } fn visit_u64< E: de::Error >( self, value: u64 ) -> Result< Self::Value, E > { value.try_into().map_err( E::custom ) } fn visit_f32< E: de::Error >( self, value: f32 ) -> Result< Self::Value, E > { Ok( value.into() ) } fn visit_f64< E: de::Error >( self, value: f64 ) -> Result< Self::Value, E > { Ok( value.into() ) } } deserializer.deserialize_f64( NumberVisitor ) } } impl Serialize for Value { #[inline] fn serialize< S: ser::Serializer >( &self, serializer: S ) -> Result< S::Ok, S::Error > { use serde_crate::ser::SerializeMap; match *self { Value::Undefined => serializer.serialize_unit_struct( "undefined" ), Value::Null => serializer.serialize_unit_struct( "null" ), Value::Bool( value ) => serializer.serialize_bool( value ), Value::Number( ref value ) => value.serialize( serializer ), Value::Symbol( _ ) => unimplemented!( "Serialization of symbols is unimplemented!" ), Value::String( ref value ) => serializer.serialize_str( value ), Value::Reference( ref reference ) => { if Array::instance_of( reference ) { let array: Array = reference.try_into().unwrap(); let value: Vec< Value > = array.into(); value.serialize( serializer ) } else if Object::instance_of( reference ) { let object: Object = reference.try_into().unwrap(); let value: BTreeMap< String, Value > = object.into(); let mut map = try!( serializer.serialize_map( Some( value.len() ) ) ); for (key, value) in value { try!( map.serialize_key( &key ) ); try!( map.serialize_value( &value ) ); } map.end() } else { let map = try!( serializer.serialize_map( None ) ); map.end() } } } } } impl< 'de > Deserialize< 'de > for Value { #[inline] fn deserialize< D: de::Deserializer< 'de > >( deserializer: D ) -> Result< Self, D::Error > { struct ValueVisitor; impl< 'de > Visitor< 'de > for ValueVisitor { type Value = Value; fn expecting( &self, formatter: &mut fmt::Formatter ) -> fmt::Result { formatter.write_str( "a value which is convertible into a JavaScript value" ) } fn visit_bool< E: de::Error >( self, value: bool ) -> Result< Self::Value, E > { Ok( value.into() ) } fn visit_i8< E: de::Error >( self, value: i8 ) -> Result< Self::Value, E > { Ok( value.into() ) } fn visit_i16< E: de::Error >( self, value: i16 ) -> Result< Self::Value, E > { Ok( value.into() ) } fn visit_i32< E: de::Error >( self, value: i32 ) -> Result< Self::Value, E > { Ok( value.into() ) } fn visit_i64< E: de::Error >( self, value: i64 ) -> Result< Self::Value, E > { value.try_into().map_err( E::custom ) } fn visit_u8< E: de::Error >( self, value: u8 ) -> Result< Self::Value, E > { Ok( value.into() ) } fn visit_u16< E: de::Error >( self, value: u16 ) -> Result< Self::Value, E > { Ok( value.into() ) } fn visit_u32< E: de::Error >( self, value: u32 ) -> Result< Self::Value, E > { Ok( value.into() ) } fn visit_u64< E: de::Error >( self, value: u64 ) -> Result< Self::Value, E > { value.try_into().map_err( E::custom ) } fn visit_f32< E: de::Error >( self, value: f32 ) -> Result< Self::Value, E > { Ok( value.into() ) } fn visit_f64< E: de::Error >( self, value: f64 ) -> Result< Self::Value, E > { Ok( value.into() ) } fn visit_char< E: de::Error >( self, value: char ) -> Result< Self::Value, E > { Ok( value.into() ) } fn visit_str< E: de::Error >( self, value: &str ) -> Result< Self::Value, E > { Ok( value.into() ) } fn visit_string< E: de::Error >( self, value: String ) -> Result< Self::Value, E > { Ok( value.into() ) } fn visit_unit< E: de::Error >( self ) -> Result< Self::Value, E > { Ok( Null.into() ) } fn visit_none< E: de::Error >( self ) -> Result< Self::Value, E > { Ok( Null.into() ) } fn visit_some< D: de::Deserializer< 'de > >( self, deserializer: D ) -> Result< Self::Value, D::Error > { deserializer.deserialize_any( self ) } fn visit_seq< V: de::SeqAccess< 'de > >( self, mut visitor: V ) -> Result< Self::Value, V::Error > { let mut output: Vec< Value > = Vec::with_capacity( visitor.size_hint().unwrap_or( 0 ) ); while let Some( element ) = visitor.next_element()? { output.push( element ); } Ok( output.into() ) } fn visit_map< V: de::MapAccess< 'de > >( self, mut visitor: V ) -> Result< Self::Value, V::Error > { let mut output: BTreeMap< String, Value > = BTreeMap::new(); while let Some( (key, value) ) = visitor.next_entry()? { output.insert( key, value ); } Ok( output.into() ) } fn visit_bytes< E: de::Error >( self, value: &[u8] ) -> Result< Self::Value, E > { Ok( value.into() ) } fn visit_byte_buf< E: de::Error >( self, value: Vec< u8 > ) -> Result< Self::Value, E > { Ok( value.into() ) } // Not really sure how (if?) to implement these at this point: // fn visit_newtype_struct< D: de::Deserializer< 'de > >( self, deserializer: D ) -> Result< Self::Value, D::Error > { // unimplemented!(); // } // fn visit_enum< V: de::EnumAccess >( self, visitor: V ) -> Result< Self::Value, V::Error > { // unimplemented!(); // } } deserializer.deserialize_any( ValueVisitor ) } } #[derive(Clone, PartialEq, Eq, Debug)] enum ConversionErrorKind { InvalidKey, NumberConversionError( number::ConversionError ), Custom( String ) } /// A structure denoting a conversion error encountered during /// serialization or deserialization. #[derive(Clone, PartialEq, Eq, Debug)] pub struct ConversionError { kind: ConversionErrorKind } impl ConversionError { fn invalid_key() -> Self { ConversionError { kind: ConversionErrorKind::InvalidKey } } } impl fmt::Display for ConversionError { fn fmt( &self, formatter: &mut fmt::Formatter ) -> Result< (), fmt::Error > { let message = error::Error::description( self ); write!( formatter, "{}", message ) } } impl error::Error for ConversionError { fn description( &self ) -> &str { match self.kind { ConversionErrorKind::InvalidKey => "key must be either a string or an integer", ConversionErrorKind::NumberConversionError( ref error ) => error.description(), ConversionErrorKind::Custom( ref message ) => message.as_str() } } } impl ser::Error for ConversionError { fn custom< T: fmt::Display >( message: T ) -> Self { ConversionError { kind: ConversionErrorKind::Custom( message.to_string() ) } } } impl de::Error for ConversionError { fn custom< T: fmt::Display >( message: T ) -> Self { ConversionError { kind: ConversionErrorKind::Custom( message.to_string() ) } } } impl From< number::ConversionError > for ConversionError { fn from( error: number::ConversionError ) -> Self { ConversionError { kind: ConversionErrorKind::NumberConversionError( error ) } } } impl From< ConversionError > for value::ConversionError { fn from( error: ConversionError ) -> Self { match error.kind { ConversionErrorKind::InvalidKey => value::ConversionError::Custom( "key must be either a string or an integer".to_owned() ), ConversionErrorKind::NumberConversionError( error ) => error.into(), ConversionErrorKind::Custom( message ) => value::ConversionError::Custom( message ) } } } #[derive(Debug)] pub struct Serializer { } impl Serializer { pub fn new() -> Self { Serializer {} } } impl< 'a > ser::Serializer for &'a mut Serializer { type Ok = Value; type Error = ConversionError; type SerializeSeq = SerializeVec; type SerializeTuple = SerializeVec; type SerializeTupleStruct = SerializeVec; type SerializeTupleVariant = SerializeTupleVariant; type SerializeMap = SerializeMap; type SerializeStruct = SerializeMap; type SerializeStructVariant = SerializeStructVariant; fn serialize_bool( self, value: bool ) -> Result< Self::Ok, Self::Error > { Ok( value.into() ) } fn serialize_i8( self, value: i8 ) -> Result< Self::Ok, Self::Error > { Ok( value.into() ) } fn serialize_i16( self, value: i16 ) -> Result< Self::Ok, Self::Error > { Ok( value.into() ) } fn serialize_i32( self, value: i32 ) -> Result< Self::Ok, Self::Error > { Ok( value.into() ) } fn serialize_i64( self, value: i64 ) -> Result< Self::Ok, Self::Error > { Ok( value.try_into()? ) } fn serialize_u8( self, value: u8 ) -> Result< Self::Ok, Self::Error > { Ok( value.into() ) } fn serialize_u16( self, value: u16 ) -> Result< Self::Ok, Self::Error > { Ok( value.into() ) } fn serialize_u32( self, value: u32 ) -> Result< Self::Ok, Self::Error > { Ok( value.into() ) } fn serialize_u64( self, value: u64 ) -> Result< Self::Ok, Self::Error > { Ok( value.try_into()? ) } fn serialize_f32( self, value: f32 ) -> Result< Self::Ok, Self::Error > { Ok( value.into() ) } fn serialize_f64( self, value: f64 ) -> Result< Self::Ok, Self::Error > { Ok( value.into() ) } fn serialize_char( self, value: char ) -> Result< Self::Ok, Self::Error > { Ok( value.into() ) } fn serialize_str( self, value: &str ) -> Result< Self::Ok, Self::Error > { Ok( value.into() ) } fn serialize_bytes( self, value: &[u8] ) -> Result< Self::Ok, Self::Error > { Ok( value.into() ) } fn serialize_none( self ) -> Result< Self::Ok, Self::Error > { self.serialize_unit() } fn serialize_some< T: ?Sized + Serialize >( self, value: &T ) -> Result< Self::Ok, Self::Error > { value.serialize( self ) } fn serialize_unit( self ) -> Result< Self::Ok, Self::Error > { Ok( Null.into() ) } fn serialize_unit_struct( self, _name: &'static str ) -> Result< Self::Ok, Self::Error > { self.serialize_unit() } fn serialize_unit_variant( self, _name: &'static str, _variant_index: u32, variant: &'static str ) -> Result< Self::Ok, Self::Error > { self.serialize_str( variant ) } fn serialize_newtype_struct< T: ?Sized + Serialize >( self, _name: &'static str, value: &T ) -> Result< Self::Ok, Self::Error > { value.serialize( self ) } fn serialize_newtype_variant< T: ?Sized + Serialize >( self, _name: &'static str, _variant_index: u32, variant: &'static str, value: &T ) -> Result< Self::Ok, Self::Error > { let mut object = BTreeMap::new(); object.insert( String::from( variant ), to_value( &value )? ); let object: Object = object.into(); Ok( Value::Reference( object.into() ) ) } fn serialize_seq( self, length: Option< usize > ) -> Result< Self::SerializeSeq, Self::Error > { Ok( SerializeVec { elements: Vec::with_capacity( length.unwrap_or( 0 ) ) }) } fn serialize_tuple( self, length: usize ) -> Result< Self::SerializeTuple, Self::Error > { self.serialize_seq( Some( length ) ) } fn serialize_tuple_struct( self, _name: &'static str, length: usize ) -> Result< Self::SerializeTupleStruct, Self::Error > { self.serialize_seq( Some( length ) ) } fn serialize_tuple_variant( self, _name: &'static str, _variant_index: u32, variant: &'static str, length: usize ) -> Result< Self::SerializeTupleVariant, Self::Error > { Ok( SerializeTupleVariant { name: String::from( variant ), elements: Vec::with_capacity( length ), }) } fn serialize_map( self, _length: Option< usize > ) -> Result< Self::SerializeMap, Self::Error > { Ok( SerializeMap { map: BTreeMap::new(), next_key: None, }) } fn serialize_struct( self, _name: &'static str, length: usize ) -> Result< Self::SerializeStruct, Self::Error > { self.serialize_map( Some( length ) ) } fn serialize_struct_variant( self, _name: &'static str, _variant_index: u32, variant: &'static str, _length: usize ) -> Result< Self::SerializeStructVariant, Self::Error > { Ok( SerializeStructVariant { name: String::from( variant ), map: BTreeMap::new(), }) } } #[doc(hidden)] #[cfg_attr(feature = "cargo-clippy", allow(needless_pass_by_value))] #[inline] pub fn to_value< T: Serialize >( value: T ) -> Result< Value, ConversionError > { let mut serializer = Serializer {}; value.serialize( &mut serializer ) } #[doc(hidden)] #[inline] pub fn from_value< 'de, T: Deserialize< 'de > >( value: Value ) -> Result< T, ConversionError > { Deserialize::deserialize( value ) } #[doc(hidden)] #[derive(Debug)] pub struct SerializeVec { elements: Vec< Value >, } #[doc(hidden)] #[derive(Debug)] pub struct SerializeTupleVariant { name: String, elements: Vec< Value >, } #[doc(hidden)] #[derive(Debug)] pub struct SerializeMap { map: BTreeMap< String, Value >, next_key: Option< String >, } #[doc(hidden)] #[derive(Debug)] pub struct SerializeStructVariant { name: String, map: BTreeMap< String, Value >, } impl ser::SerializeSeq for SerializeVec { type Ok = Value; type Error = ConversionError; #[inline] fn serialize_element< T: ?Sized + Serialize >( &mut self, value: &T ) -> Result< (), Self::Error > { self.elements.push( to_value( &value )? ); Ok(()) } #[inline] fn end( self ) -> Result< Self::Ok, Self::Error > { Ok( self.elements.into() ) } } impl ser::SerializeTuple for SerializeVec { type Ok = Value; type Error = ConversionError; #[inline] fn serialize_element< T: ?Sized + Serialize >( &mut self, value: &T ) -> Result< (), Self::Error > { ser::SerializeSeq::serialize_element( self, value ) } #[inline] fn end( self ) -> Result< Self::Ok, Self::Error > { ser::SerializeSeq::end( self ) } } impl ser::SerializeTupleStruct for SerializeVec { type Ok = Value; type Error = ConversionError; fn serialize_field< T: ?Sized + Serialize >( &mut self, value: &T ) -> Result< (), Self::Error > { ser::SerializeSeq::serialize_element( self, value ) } fn end( self ) -> Result< Self::Ok, Self::Error > { ser::SerializeSeq::end( self ) } } impl ser::SerializeTupleVariant for SerializeTupleVariant { type Ok = Value; type Error = ConversionError; fn serialize_field< T: ?Sized + Serialize >( &mut self, value: &T ) -> Result< (), Self::Error > { self.elements.push( to_value( &value )? ); Ok(()) } fn end( self ) -> Result< Self::Ok, Self::Error > { let mut object: BTreeMap< String, Value > = BTreeMap::new(); object.insert( self.name, self.elements.into() ); Ok( object.into() ) } } impl ser::SerializeMap for SerializeMap { type Ok = Value; type Error = ConversionError; fn serialize_key< T: ?Sized + Serialize >( &mut self, key: &T ) -> Result< (), Self::Error > { match to_value( &key )? { Value::String( string ) => self.next_key = Some( string ), Value::Number( number ) => { if let Ok( value ) = number.try_into() { let value: u64 = value; self.next_key = Some( value.to_string() ); } else if let Ok( value ) = number.try_into() { let value: i64 = value; self.next_key = Some( value.to_string() ); } else { return Err( ConversionError::invalid_key() ) } }, _ => return Err( ConversionError::invalid_key() ) } Ok(()) } fn serialize_value< T: ?Sized + Serialize >( &mut self, value: &T ) -> Result< (), Self::Error > { let key = self.next_key.take(); // Panic because this indicates a bug in the program rather than an // expected failure. let key = key.expect( "serialize_value called before serialize_key" ); self.map.insert( key, to_value( &value )? ); Ok(()) } fn end( self ) -> Result< Self::Ok, Self::Error > { Ok( self.map.into() ) } } impl ser::SerializeStruct for SerializeMap { type Ok = Value; type Error = ConversionError; fn serialize_field< T: ?Sized + Serialize >( &mut self, key: &'static str, value: &T ) -> Result< (), Self::Error > { ser::SerializeMap::serialize_key( self, key )?; ser::SerializeMap::serialize_value( self, value ) } fn end( self ) -> Result< Self::Ok, Self::Error > { ser::SerializeMap::end( self ) } } impl ser::SerializeStructVariant for SerializeStructVariant { type Ok = Value; type Error = ConversionError; fn serialize_field< T: ?Sized + Serialize >( &mut self, key: &'static str, value: &T ) -> Result< (), Self::Error > { self.map.insert( String::from( key ), to_value( &value )? ); Ok(()) } fn end( self ) -> Result< Self::Ok, Self::Error > { let mut object: BTreeMap< String, Value > = BTreeMap::new(); object.insert( self.name, self.map.into() ); Ok( object.into() ) } } macro_rules! number_deserializer { ($([$name:ident $visitor:ident $type:ty])+) => { $( #[inline] fn $name< V: Visitor< 'de > >( self, visitor: V ) -> Result< V::Value, Self::Error > { let value: $type = self.try_into()?; visitor.$visitor( value ) } )+ }; } impl< 'de > de::Deserializer< 'de > for Number { type Error = ConversionError; #[inline] fn deserialize_any< V: Visitor< 'de > >( self, visitor: V ) -> Result< V::Value, Self::Error > { match *get_storage( &self ) { number::Storage::I32( value ) => visitor.visit_i32( value ), number::Storage::F64( value ) => visitor.visit_f64( value ) } } number_deserializer! { [deserialize_i8 visit_i8 i8] [deserialize_i16 visit_i16 i16] [deserialize_i32 visit_i32 i32] [deserialize_i64 visit_i64 i64] [deserialize_u8 visit_u8 u8] [deserialize_u16 visit_u16 u16] [deserialize_u32 visit_u32 u32] [deserialize_u64 visit_u64 u64] [deserialize_f64 visit_f64 f64] } forward_to_deserialize_any! { bool f32 char str string unit option seq bytes byte_buf map unit_struct newtype_struct tuple_struct struct identifier tuple enum ignored_any } } // TODO: Impl for `&'a Number` and `&'a mut Number`. impl Value { fn unexpected( &self ) -> de::Unexpected { match *self { Value::Undefined => de::Unexpected::Other( "undefined" ), Value::Null => de::Unexpected::Other( "null" ), Value::Bool( value ) => de::Unexpected::Bool( value ), Value::Number( ref value ) => { match *get_storage( value ) { number::Storage::I32( value ) => de::Unexpected::Signed( value as i64 ), number::Storage::F64( value ) => de::Unexpected::Float( value ) } }, Value::Symbol( _ ) => de::Unexpected::Other( "Symbol" ), Value::String( ref value ) => de::Unexpected::Str( value ), Value::Reference( _ ) => de::Unexpected::Other( "reference to a JavaScript value" ) } } } macro_rules! value_proxy_number_deserializer { ($($name:ident)+) => { $( #[inline] fn $name< V: Visitor< 'de > >( self, visitor: V ) -> Result< V::Value, Self::Error > { match self { Value::Number( value ) => value.$name( visitor ), value => value.deserialize_any( visitor ) } } )+ }; } impl< 'de > de::Deserializer< 'de > for Value { type Error = ConversionError; #[inline] fn deserialize_any< V: Visitor< 'de > >( self, visitor: V ) -> Result< V::Value, Self::Error > { match self { Value::Undefined => visitor.visit_unit(), Value::Null => visitor.visit_unit(), Value::Bool( value ) => visitor.visit_bool( value ), Value::Number( value ) => de::Deserializer::deserialize_any( value, visitor ), Value::Symbol( _ ) => unimplemented!( "Deserialization of symbols is unimplemented!" ), Value::String( value ) => visitor.visit_string( value ), Value::Reference( reference ) => { if Array::instance_of( &reference ) { let value: Array = reference.try_into().unwrap(); let value: Vec< _ > = value.into(); let length = value.len(); let mut deserializer = SeqDeserializer::new( value ); let seq = visitor.visit_seq( &mut deserializer )?; let remaining = deserializer.iter.len(); if remaining == 0 { Ok( seq ) } else { Err( de::Error::invalid_length( length, &"fewer elements in the array" ) ) } } else if Object::instance_of( &reference ) { let value: Object = reference.try_into().unwrap(); let value: BTreeMap< _, _ > = value.into(); let length = value.len(); let mut deserializer = MapDeserializer::new( value ); let map = visitor.visit_map( &mut deserializer )?; let remaining = deserializer.iter.len(); if remaining == 0 { Ok( map ) } else { Err( de::Error::invalid_length( length, &"fewer elements in the object" ) ) } } else { unimplemented!(); // TODO: ? } } } } value_proxy_number_deserializer! { deserialize_i8 deserialize_i16 deserialize_i32 deserialize_i64 deserialize_u8 deserialize_u16 deserialize_u32 deserialize_u64 deserialize_f32 deserialize_f64 } #[inline] fn deserialize_option< V: Visitor< 'de > >( self, visitor: V ) -> Result< V::Value, Self::Error > { match self { Value::Undefined => visitor.visit_none(), Value::Null => visitor.visit_none(), _ => visitor.visit_some( self ) } } #[inline] fn deserialize_enum< V: Visitor< 'de > >( self, _name: &str, _variants: &'static [&'static str], visitor: V ) -> Result< V::Value, Self::Error > { let (variant, value) = match self { Value::Reference( reference ) => { let value: Object = match reference.try_into() { Ok( object ) => object, Err( _ ) => return Err( de::Error::invalid_value( de::Unexpected::Map, &"map with a single key" ) ) }; let value: BTreeMap< _, _ > = value.into(); let mut iter = value.into_iter(); let (variant, value) = match iter.next() { Some( value ) => value, None => { return Err( de::Error::invalid_value( de::Unexpected::Map, &"map with a single key" ) ); } }; // Enums are encoded as objects with a single key:value pair. if iter.next().is_some() { return Err( de::Error::invalid_value( de::Unexpected::Map, &"map with a single key" ) ); } (variant, Some( value )) }, Value::String( variant ) => (variant, None), other => { return Err( de::Error::invalid_type( other.unexpected(), &"string or map" ) ); } }; visitor.visit_enum( EnumDeserializer { variant: variant, value: value, }) } #[inline] fn deserialize_newtype_struct< V: Visitor< 'de > >( self, _name: &'static str, visitor: V ) -> Result< V::Value, Self::Error > { visitor.visit_newtype_struct( self ) } forward_to_deserialize_any! { bool char str string unit seq bytes byte_buf map unit_struct tuple_struct struct identifier tuple ignored_any } } struct EnumDeserializer { variant: String, value: Option< Value >, } impl< 'de > de::EnumAccess< 'de > for EnumDeserializer { type Error = ConversionError; type Variant = VariantDeserializer; fn variant_seed< V: de::DeserializeSeed< 'de > >( self, seed: V ) -> Result< (V::Value, VariantDeserializer), Self::Error > { let variant = self.variant.into_deserializer(); let visitor = VariantDeserializer { value: self.value }; seed.deserialize( variant ).map( |v| (v, visitor) ) } } struct VariantDeserializer { value: Option< Value >, } impl< 'de > de::VariantAccess< 'de > for VariantDeserializer { type Error = ConversionError; fn unit_variant( self ) -> Result< (), Self::Error > { match self.value { Some( value ) => de::Deserialize::deserialize( value ), None => Ok(()), } } fn newtype_variant_seed< T: de::DeserializeSeed< 'de > >( self, seed: T ) -> Result< T::Value, Self::Error > { match self.value { Some( value ) => seed.deserialize( value ), None => Err( de::Error::invalid_type( de::Unexpected::UnitVariant, &"newtype variant" ) ), } } fn tuple_variant< V: Visitor< 'de > >( self, _length: usize, visitor: V ) -> Result< V::Value, Self::Error > { match self.value { Some( Value::Reference( reference ) ) => { let array: Array = match reference.try_into() { Ok( array ) => array, Err( _ ) => return Err( de::Error::invalid_type( de::Unexpected::UnitVariant, &"tuple variant" ) ) }; de::Deserializer::deserialize_any( SeqDeserializer::new( array.into() ), visitor ) }, Some( other ) => Err( de::Error::invalid_type( other.unexpected(), &"tuple variant" ) ), None => Err( de::Error::invalid_type( de::Unexpected::UnitVariant, &"tuple variant" ) ) } } fn struct_variant< V: Visitor< 'de > >( self, _fields: &'static [&'static str], visitor: V ) -> Result< V::Value, Self::Error > { match self.value { Some( Value::Reference( reference ) ) => { let object: Object = match reference.try_into() { Ok( object ) => object, Err( _ ) => return Err( de::Error::invalid_type( de::Unexpected::UnitVariant, &"struct variant" ) ) }; de::Deserializer::deserialize_any( MapDeserializer::new( object.into() ), visitor ) }, Some( other ) => Err( de::Error::invalid_type( other.unexpected(), &"struct variant" ) ), _ => Err( de::Error::invalid_type( de::Unexpected::UnitVariant, &"struct variant" ) ) } } } struct SeqDeserializer { iter: vec::IntoIter< Value >, } impl SeqDeserializer { fn new( vec: Vec< Value >) -> Self { SeqDeserializer { iter: vec.into_iter(), } } } impl< 'de > de::Deserializer< 'de > for SeqDeserializer { type Error = ConversionError; #[inline] fn deserialize_any< V: Visitor< 'de > >( mut self, visitor: V ) -> Result< V::Value, Self::Error > { let length = self.iter.len(); if length == 0 { visitor.visit_unit() } else { let ret = visitor.visit_seq( &mut self )?; let remaining = self.iter.len(); if remaining == 0 { Ok( ret ) } else { Err( de::Error::invalid_length( length, &"fewer elements in array" ) ) } } } forward_to_deserialize_any! { bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option seq bytes byte_buf map unit_struct newtype_struct tuple_struct struct identifier tuple enum ignored_any } } impl< 'de > de::SeqAccess< 'de > for SeqDeserializer { type Error = ConversionError; fn next_element_seed< T: de::DeserializeSeed< 'de > >( &mut self, seed: T ) -> Result< Option< T::Value >, Self::Error > { match self.iter.next() { Some( value ) => seed.deserialize( value ).map( Some ), None => Ok( None ), } } fn size_hint( &self ) -> Option< usize > { match self.iter.size_hint() { (lower, Some( upper )) if lower == upper => Some( upper ), _ => None } } } struct MapDeserializer { iter: as IntoIterator>::IntoIter, value: Option< Value >, } impl MapDeserializer { fn new( map: BTreeMap< String, Value > ) -> Self { MapDeserializer { iter: map.into_iter(), value: None, } } } impl< 'de > de::MapAccess< 'de > for MapDeserializer { type Error = ConversionError; fn next_key_seed< T: de::DeserializeSeed< 'de > >( &mut self, seed: T ) -> Result< Option< T::Value >, Self::Error> { match self.iter.next() { Some( (key, value) ) => { self.value = Some( value ); seed.deserialize( key.into_deserializer() ).map( Some ) } None => Ok( None ) } } fn next_value_seed< T: de::DeserializeSeed< 'de > >( &mut self, seed: T ) -> Result< T::Value, Self::Error > { match self.value.take() { Some( value ) => seed.deserialize( value ), None => Err( de::Error::custom( "value is missing" ) ), } } fn size_hint( &self ) -> Option< usize > { match self.iter.size_hint() { (lower, Some( upper )) if lower == upper => Some( upper ), _ => None } } } impl< 'de > de::Deserializer< 'de > for MapDeserializer { type Error = ConversionError; #[inline] fn deserialize_any< V: Visitor< 'de > >( self, visitor: V ) -> Result< V::Value, Self::Error > { visitor.visit_map( self ) } forward_to_deserialize_any! { bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option seq bytes byte_buf map unit_struct newtype_struct tuple_struct struct identifier tuple enum ignored_any } } #[doc(hidden)] #[macro_export] macro_rules! __js_serializable_serde_boilerplate { (($($impl_arg:tt)*) ($($kind_arg:tt)*) ($($bounds:tt)*)) => { __js_serializable_boilerplate!( ($($impl_arg)*) ($($kind_arg)*) ($($bounds)*) ); impl< $($impl_arg),* > $crate::private::JsSerialize for $($kind_arg)* where $($bounds)* { #[inline] fn _into_js< 'x >( &'x self ) -> $crate::private::SerializedValue< 'x > { let value = $crate::private::to_value( self ).unwrap(); $crate::private::serialize_value( value ) } } impl< $($impl_arg),* > $crate::unstable::TryFrom< $($kind_arg)* > for $crate::Value where $($bounds)* { type Error = $crate::serde::ConversionError; #[inline] fn try_from( value: $($kind_arg)* ) -> Result< Self, Self::Error > { $crate::private::to_value( value ) } } impl< '_a, $($impl_arg),* > $crate::unstable::TryFrom< &'_a $($kind_arg)* > for $crate::Value where $($bounds)* { type Error = $crate::serde::ConversionError; #[inline] fn try_from( value: &'_a $($kind_arg)* ) -> Result< Self, Self::Error > { $crate::private::to_value( value ) } } impl< '_a, $($impl_arg),* > $crate::unstable::TryFrom< &'_a mut $($kind_arg)* > for $crate::Value where $($bounds)* { type Error = $crate::serde::ConversionError; #[inline] fn try_from( value: &'_a mut $($kind_arg)* ) -> Result< Self, Self::Error > { $crate::private::to_value( value ) } } } } #[doc(hidden)] #[macro_export] macro_rules! __js_deserializable_serde_boilerplate { (($($impl_arg:tt)*) ($($kind_arg:tt)*) ($($bounds:tt)*)) => { impl< $($impl_arg),* > $crate::unstable::TryFrom< $crate::Value > for $($kind_arg)* where $($bounds)* { type Error = $crate::serde::ConversionError; #[inline] fn try_from( value: $crate::Value ) -> Result< Self, Self::Error > { $crate::private::from_value( value ) } } } } /// A macro which makes it possible to pass an instance of a given type /// implementing Serde's `Serialize` into the [js!](macro.js.html) macro. /// /// For types defined outside of your crate you can also use the [Serde](serde/struct.Serde.html) /// newtype to make them serializable indirectly. /// /// # Examples /// /// ``` /// #[derive(Serialize, Debug)] /// struct Person { /// name: String, /// age: i32 /// } /// /// js_serializable!( Person ); /// /// let person = Person { /// name: "Bob".to_owned(), /// age: 33 /// }; /// /// js! { /// var person = @{person}; /// console.log( person.name + " is " + person.age + " years old." ); /// }; /// ``` /// /// This macro also accepts generics: /// /// ``` /// trait Foobar {} /// /// #[derive(Serialize)] /// struct Wrapper< 'a, T: Serialize + 'a >( &'a T ); /// /// js_serializable!( impl< 'a, T > for Wrapper< 'a, T > where T: Serialize + Foobar ); /// ``` #[macro_export] macro_rules! js_serializable { ($kind:tt) => { $crate::__js_serializable_serde_boilerplate!( () ($kind) () ); }; (impl< $($impl_arg:tt),* > for $kind:ty where $($bounds:tt)*) => { $crate::__js_serializable_serde_boilerplate!( ($($impl_arg),*) ($kind) ($($bounds)*) ); }; (impl< $($impl_arg:tt),* > for $kind:ty) => { $crate::__js_serializable_serde_boilerplate!( ($($impl_arg),*) ($kind) () ); }; } /// A macro which makes it possible to convert an instance of a given type /// implementing Serde's `Deserialize` into a [Value](enum.Value.html) using /// [TryInto](unstable/trait.TryInto.html). /// /// For types defined outside of your crate you can also use the [Serde](serde/struct.Serde.html) /// newtype to make them deserializable indirectly. /// /// # Examples /// /// ``` /// #[derive(Deserialize, Debug)] /// struct Person { /// name: String, /// age: i32 /// } /// /// js_deserializable!( Person ); /// /// let value = js! { /// return { /// name: "Bob", /// age: 33 /// }; /// }; /// /// let structure: Person = value.try_into().unwrap(); /// assert_eq!( structure.name, "Bob" ); /// assert_eq!( structure.age, 33 ); /// ``` /// /// This macro also accepts generics just as the [js_serializable!](macro.js_serializable.html) does. #[macro_export] macro_rules! js_deserializable { ($kind:tt) => { $crate::__js_deserializable_serde_boilerplate!( () ($kind) () ); }; (impl< $($impl_arg:tt),* > for $kind:ty where $($bounds:tt)*) => { $crate::__js_deserializable_serde_boilerplate!( ($($impl_arg),*) ($kind) ($($bounds)*) ); }; (impl< $($impl_arg:tt),* > for $kind:ty) => { $crate::__js_deserializable_serde_boilerplate!( ($($impl_arg),*) ($kind) () ); }; } /// A newtype which makes it possible to pass a value which implements /// Serde's `Serializable` into the [js!](macro.js.html) macro. /// /// For types defined in your crate you can also use the [js_serializable!](macro.js_serializable.html) /// macro to make them serializable directly. /// /// # Examples /// /// ``` /// #[derive(Serialize, Debug)] /// struct Person { /// name: String, /// age: i32 /// } /// /// let person = Person { /// name: "Bob".to_owned(), /// age: 33 /// }; /// /// js! { /// var person = @{Serde( person )}; /// console.log( person.name + " is " + person.age + " years old." ); /// }; /// ``` pub struct Serde< T >( pub T ); impl< T: fmt::Debug > fmt::Debug for Serde< T > { #[inline] fn fmt( &self, formatter: &mut fmt::Formatter ) -> Result< (), fmt::Error > { self.0.fmt( formatter ) } } impl< T: Serialize > JsSerialize for Serde< T > { #[inline] fn _into_js< 'a >( &'a self ) -> SerializedValue< 'a > { let value = to_value( &self.0 ).unwrap(); global_arena::serialize_value( value ) } } impl< T: Serialize > TryFrom< Serde< T > > for Value { type Error = ConversionError; #[inline] fn try_from( value: Serde< T > ) -> Result< Self, Self::Error > { to_value( &value.0 ) } } impl< 'a, T: Serialize > TryFrom< &'a Serde< T > > for Value { type Error = ConversionError; #[inline] fn try_from( value: &'a Serde< T > ) -> Result< Self, Self::Error > { to_value( &value.0 ) } } impl< 'a, T: Serialize > TryFrom< &'a mut Serde< T > > for Value { type Error = ConversionError; #[inline] fn try_from( value: &'a mut Serde< T > ) -> Result< Self, Self::Error > { to_value( &value.0 ) } } impl< 'de, T: Deserialize< 'de > > TryFrom< Value > for Serde< T > { type Error = ConversionError; #[inline] fn try_from( value: Value ) -> Result< Self, Self::Error > { Ok( Serde( from_value( value )? ) ) } } impl< 'de, T: Deserialize< 'de > > TryFrom< Value > for Option< Serde< T > > { type Error = ConversionError; #[inline] fn try_from( value: Value ) -> Result< Self, Self::Error > { match value { Value::Undefined | Value::Null => Ok( None ), value => value.try_into().map( Some ) } } } __js_serializable_boilerplate!( impl< T > for Serde< T > where T: Serialize ); #[cfg(test)] mod tests { use super::*; use serde_json; #[test] fn serialize_undefined() { // This is technically incorrect as `undefined` is not serializable into JSON, // but serde is generic so it serialized it anyway. assert_eq!( serde_json::to_string( &Undefined ).unwrap(), "null" ); } #[test] fn serialize_null() { assert_eq!( serde_json::to_string( &Null ).unwrap(), "null" ); } #[test] fn serialize_number_negative() { let value: Number = (-123_i32).into(); assert_eq!( serde_json::to_string( &value ).unwrap(), "-123" ); } #[test] fn serialize_number_positive() { let value: Number = 123_i32.into(); assert_eq!( serde_json::to_string( &value ).unwrap(), "123" ); } #[test] fn serialize_number_float() { let value: Number = 3.33_f64.into(); assert_eq!( serde_json::to_string( &value ).unwrap(), "3.33" ); } #[test] fn serialize_value_undefined() { let value: Value = Undefined.into(); assert_eq!( serde_json::to_string( &value ).unwrap(), "null" ); } #[test] fn serialize_value_null() { let value: Value = Null.into(); assert_eq!( serde_json::to_string( &value ).unwrap(), "null" ); } #[test] fn serialize_value_bool_true() { let value: Value = true.into(); assert_eq!( serde_json::to_string( &value ).unwrap(), "true" ); } #[test] fn serialize_value_bool_false() { let value: Value = false.into(); assert_eq!( serde_json::to_string( &value ).unwrap(), "false" ); } #[test] fn serialize_value_number() { let value: Value = (123_i32).into(); assert_eq!( serde_json::to_string( &value ).unwrap(), "123" ); } #[test] fn serialize_value_string() { let value: Value = "死神はりんごしか食べない".into(); assert_eq!( serde_json::to_string( &value ).unwrap(), "\"死神はりんごしか食べない\"" ); } #[test] fn serialize_value_array() { let value: Value = (&[true, false][..]).into(); assert_eq!( serde_json::to_string( &value ).unwrap(), "[true,false]" ); } #[test] fn serialize_value_object() { use std::collections::BTreeMap; let mut map = BTreeMap::new(); map.insert( "1", "one" ); map.insert( "2", "two" ); let value: Value = map.into(); assert_eq!( serde_json::to_string( &value ).unwrap(), "{\"1\":\"one\",\"2\":\"two\"}" ); } #[test] fn deserialize_value_null() { let value: Value = serde_json::from_str( "null" ).unwrap(); assert_eq!( value, Value::Null ); } #[test] fn deserialize_value_bool_false() { let value: Value = serde_json::from_str( "false" ).unwrap(); assert_eq!( value, Value::Bool( false ) ); } #[test] fn deserialize_value_bool_true() { let value: Value = serde_json::from_str( "true" ).unwrap(); assert_eq!( value, Value::Bool( true ) ); } #[test] fn deserialize_value_number_integer() { let value: Value = serde_json::from_str( "33" ).unwrap(); assert_eq!( value, Value::Number( 33.into() ) ); } #[test] fn deserialize_value_number_float() { let value: Value = serde_json::from_str( "33.33" ).unwrap(); assert_eq!( value, Value::Number( 33.33.into() ) ); } #[test] fn deserialize_value_string() { let value: Value = serde_json::from_str( "\"Bob\"" ).unwrap(); assert_eq!( value, Value::String( "Bob".to_owned() ) ); } #[test] fn deserialize_value_array() { let value: Value = serde_json::from_str( "[true, false]" ).unwrap(); assert_eq!( value.is_array(), true ); let value: Vec< Value > = value.try_into().unwrap(); assert_eq!( value, vec![ Value::Bool( true ), Value::Bool( false ) ] ); } #[test] fn deserialize_value_object() { let value: Value = serde_json::from_str( "{\"1\":\"one\",\"2\":\"two\"}" ).unwrap(); let mut map: BTreeMap< String, Value > = BTreeMap::new(); map.insert( "1".to_owned(), Value::String( "one".to_owned() ) ); map.insert( "2".to_owned(), Value::String( "two".to_owned() ) ); let value: BTreeMap< _, _ > = value.into_object().unwrap().into(); assert_eq!( value, map ); } #[derive(Serialize, Deserialize, Debug)] struct Structure { number: i32, string: String } #[derive(PartialEq, Serialize, Deserialize, Debug)] struct StructureSerializable { number: i32, string: String } js_serializable!( StructureSerializable ); js_deserializable!( StructureSerializable ); #[test] fn serialization_into_value_through_macro() { let structure = StructureSerializable { number: 123, string: "Hello!".to_owned() }; let value: Value = structure.try_into().unwrap(); let mut map = BTreeMap::new(); map.insert( "number".to_owned(), Value::Number( 123.into() ) ); map.insert( "string".to_owned(), Value::String( "Hello!".to_owned() ) ); let value: BTreeMap< _, _ > = value.into_object().unwrap().into(); assert_eq!( value, map ); } #[test] fn serialization_into_javascript_through_macro() { let structure = StructureSerializable { number: 123, string: "Hello!".to_owned() }; let result = js! { var object = @{structure}; return object.number === 123 && object.string === "Hello!" && Object.keys( object ).length == 2; }; assert_eq!( result, true ); } #[test] fn serialization_into_value_through_newtype() { let structure = Structure { number: 123, string: "Hello!".to_owned() }; let value: Value = Serde( structure ).try_into().unwrap(); let mut map = BTreeMap::new(); map.insert( "number".to_owned(), Value::Number( 123.into() ) ); map.insert( "string".to_owned(), Value::String( "Hello!".to_owned() ) ); let value: BTreeMap< _, _ > = value.into_object().unwrap().into(); assert_eq!( value, map ); } #[test] fn serialization_into_javascript_through_newtype() { let structure = Structure { number: 123, string: "Hello!".to_owned() }; let result = js! { var object = @{Serde( structure )}; return object.number === 123 && object.string === "Hello!" && Object.keys( object ).length == 2; }; assert_eq!( result, true ); } #[test] fn deserialization_into_value_through_macro() { let value = js! { return { number: 123, string: "Hello!" }; }; let structure: StructureSerializable = value.try_into().unwrap(); assert_eq!( structure.number, 123 ); assert_eq!( structure.string, "Hello!" ); } #[test] fn deserialization_into_value_through_newtype() { let value = js! { return { number: 123, string: "Hello!" }; }; let structure: Serde< Structure > = value.try_into().unwrap(); assert_eq!( structure.0.number, 123 ); assert_eq!( structure.0.string, "Hello!" ); } #[test] fn deserialization_into_option_through_newtype() { let value = js! { return { number: 123, string: "Hello!" }; }; let structure: Option< Serde< Structure > > = value.try_into().unwrap(); let structure = structure.unwrap(); assert_eq!( structure.0.number, 123 ); assert_eq!( structure.0.string, "Hello!" ); let structure: Option< Serde< Structure > > = Value::Null.try_into().unwrap(); assert!( structure.is_none() ); } #[test] fn serialization_and_deserialization_of_btreemap_with_serializable_values() { let mut original = BTreeMap::new(); original.insert( "key", StructureSerializable { number: 123, string: "Hello!".to_owned() }); let value: Value = (&original).into(); let deserialized: BTreeMap< String, StructureSerializable > = value.try_into().unwrap(); assert_eq!( original.len(), deserialized.len() ); assert_eq!( original.get( "key" ).unwrap(), deserialized.get( "key" ).unwrap() ); } #[test] fn serialization_and_deserialization_of_array_with_serializable_elements() { let original = vec![ StructureSerializable { number: 123, string: "Hello!".to_owned() }]; let value: Value = (&original).into(); let deserialized: Vec< StructureSerializable > = value.try_into().unwrap(); assert_eq!( original.len(), deserialized.len() ); assert_eq!( original[ 0 ], deserialized[ 0 ] ); } #[test] fn deserialization_of_a_big_number() { #[derive(Deserialize, Debug)] struct Struct { number: u64 } let structure: Serde< Struct > = js!( return { number: 1535164942454 }; ).try_into().unwrap(); assert_eq!( structure.0.number, 1535164942454 ); } #[test] fn deserialization_of_a_very_big_number() { #[derive(Deserialize, Debug)] struct Struct { number: u64 } let structure: Serde< Struct > = js!( return { number: 9223372049167088120 }; ).try_into().unwrap(); assert_eq!( structure.0.number, 9223372049167087616 ); } } stdweb-0.4.20/src/ecosystem/serde_json.rs010064400017500001750000000031071331624470200166140ustar0000000000000000use std::collections::BTreeMap; use serde_json::value::Value as JsonValue; use webcore::value::Value; use webcore::try_from::{TryFrom, TryInto}; use webcore::number::ConversionError; impl TryFrom< JsonValue > for Value { type Error = ConversionError; #[inline] fn try_from( value: JsonValue ) -> Result< Self, Self::Error > { let result = match value { JsonValue::Null => Value::Null, JsonValue::Bool( value ) => Value::Bool( value ), JsonValue::Number( value ) => { if let Some( value ) = value.as_u64() { Value::Number( value.try_into()? ) } else if let Some( value ) = value.as_i64() { Value::Number( value.try_into()? ) } else { Value::Number( value.as_f64().unwrap().into() ) } }, JsonValue::String( value ) => Value::String( value ), JsonValue::Array( value ) => { let mut vector: Vec< Value > = Vec::new(); vector.reserve( value.len() ); for element in value.into_iter() { vector.push( element.try_into()? ); } vector.into() }, JsonValue::Object( value ) => { let mut map: BTreeMap< String, Value > = BTreeMap::new(); for (key, value) in value.into_iter() { map.insert( key.into(), value.try_into()? ); } map.into() } }; Ok( result ) } } stdweb-0.4.20/src/lib.rs010064400017500001750000000425361354667070600132410ustar0000000000000000//! The goal of this crate is to provide Rust bindings to the Web APIs and to allow //! a high degree of interoperability between Rust and JavaScript. //! //! ## Examples //! //! You can directly embed JavaScript code into Rust: //! //! ```rust //! let message = "Hello, 世界!"; //! let result = js! { //! alert( @{message} ); //! return 2 + 2 * 2; //! }; //! //! println!( "2 + 2 * 2 = {:?}", result ); //! ``` //! //! Closures are also supported: //! //! ```rust //! let print_hello = |name: String| { //! println!( "Hello, {}!", name ); //! }; //! //! js! { //! var print_hello = @{print_hello}; //! print_hello( "Bob" ); //! print_hello.drop(); // Necessary to clean up the closure on Rust's side. //! } //! ``` //! //! You can also pass arbitrary structures thanks to [serde]: //! //! ```rust //! #[derive(Serialize)] //! struct Person { //! name: String, //! age: i32 //! } //! //! js_serializable!( Person ); //! //! js! { //! var person = @{person}; //! console.log( person.name + " is " + person.age + " years old." ); //! }; //! ``` //! //! [serde]: https://serde.rs/ //! //! This crate also exposes a number of Web APIs, for example: //! //! ```rust //! let button = document().query_selector( "#hide-button" ).unwrap().unwrap(); //! button.add_event_listener( move |_: ClickEvent| { //! for anchor in document().query_selector_all( "#main a" ) { //! js!( @{anchor}.style = "display: none;"; ); //! } //! }); //! ``` //! //! Exposing Rust functions to JavaScript is supported too: //! //! ```rust //! #[js_export] //! fn hash( string: String ) -> String { //! let mut hasher = Sha1::new(); //! hasher.update( string.as_bytes() ); //! hasher.digest().to_string() //! } //! ``` //! //! Then you can do this from Node.js: //! //! ```js //! var hasher = require( "hasher.js" ); // Where `hasher.js` is generated from Rust code. //! console.log( hasher.hash( "Hello world!" ) ); //! ``` //! //! Or you can take the same `.js` file and use it in a web browser: //! //! ```html //! //! //! ``` //! //! If you're using [Parcel] you can also use our [experimental Parcel plugin]; //! first do this in your existing Parcel project: //! //! $ npm install --save parcel-plugin-cargo-web //! //! And then simply: //! //! ```js //! import hasher from "./hasher/Cargo.toml"; //! console.log( hasher.hash( "Hello world!" ) ); //! ``` //! //! [Parcel]: https://parceljs.org/ //! [experimental Parcel plugin]: https://github.com/koute/parcel-plugin-cargo-web #![deny( missing_docs, missing_debug_implementations, trivial_numeric_casts, unused_import_braces )] #![cfg_attr( all(test, rust_nightly), feature(linkage) // Needed for async tests. )] #![cfg_attr(rust_nightly, feature(core_intrinsics))] #![cfg_attr(feature = "nightly", feature(never_type))] #![recursion_limit="1500"] #[cfg(feature = "serde")] #[macro_use] extern crate serde as serde_crate; #[cfg(any(test, feature = "serde_json"))] extern crate serde_json; #[cfg(all(test, feature = "serde"))] #[macro_use] extern crate serde_derive; #[cfg(all(target_arch = "wasm32", target_vendor = "unknown", target_os = "unknown", not(cargo_web)))] extern crate wasm_bindgen; #[cfg(all(target_arch = "wasm32", target_vendor = "unknown", target_os = "unknown", not(cargo_web), test))] #[macro_use] extern crate wasm_bindgen_test; #[cfg(all(target_arch = "wasm32", target_vendor = "unknown", target_os = "unknown", not(cargo_web), test))] #[macro_use] extern crate stdweb_internal_test_macro; extern crate stdweb_internal_macros; #[cfg(all( target_arch = "wasm32", target_os = "unknown" ))] pub use stdweb_internal_macros::js_export; pub use stdweb_internal_macros::async_test; #[cfg(feature = "futures-support")] extern crate futures_core; #[cfg(feature = "futures-support")] extern crate futures_util; #[cfg(feature = "futures-support")] extern crate futures_channel; #[cfg(feature = "futures-support")] extern crate futures_executor; #[macro_use] extern crate stdweb_derive; #[macro_use] extern crate stdweb_internal_runtime; extern crate discard; #[cfg(all(target_arch = "wasm32", target_vendor = "unknown", target_os = "unknown", not(cargo_web), test))] wasm_bindgen_test_configure!( run_in_browser ); #[macro_use] mod webcore; mod webapi; mod ecosystem; // This is here so that our procedural macros // can work within the crate. pub(crate) mod stdweb { pub use super::*; } pub use webcore::initialization::{ initialize, event_loop }; pub use webcore::value::{ Undefined, Null, Value, Reference }; pub use webcore::number::Number; pub use webcore::object::Object; pub use webcore::array::Array; pub use webcore::symbol::Symbol; pub use webcore::unsafe_typed_array::UnsafeTypedArray; pub use webcore::mutfn::Mut; pub use webcore::once::Once; pub use webcore::instance_of::InstanceOf; pub use webcore::reference_type::ReferenceType; pub use webcore::serialization::JsSerialize; pub use webcore::discard::DiscardOnDrop; #[cfg(feature = "experimental_features_which_may_break_on_minor_version_bumps")] pub use webcore::promise::{TypedPromise, Promise, DoneHandle}; #[cfg(all( feature = "futures-support", feature = "experimental_features_which_may_break_on_minor_version_bumps" ))] pub use webcore::promise_future::{PromiseFuture, spawn_local, print_error_panic, unwrap_future}; #[cfg(feature = "serde")] /// A module with serde-related APIs. pub mod serde { pub use ecosystem::serde::{ ConversionError, Serde }; } /// A module with bindings to the Web APIs. pub mod web { #[cfg(feature = "futures-support")] pub use webapi::timer_future::{ Wait, wait, IntervalBuffered, interval_buffered }; pub use webapi::window::{ Window, window }; pub use webapi::document::{ Document, document }; pub use webapi::global::{ set_timeout, alert, confirm }; pub use webapi::cross_origin_setting::CrossOriginSetting; pub use webapi::date::Date; pub use webapi::event_target::{IEventTarget, EventTarget, EventListenerHandle}; pub use webapi::window::RequestAnimationFrameHandle; pub use webapi::node::{INode, Node, CloneKind, NodeType}; pub use webapi::element::{IElement, Element}; pub use webapi::document_fragment::DocumentFragment; pub use webapi::text_node::TextNode; pub use webapi::html_element::{IHtmlElement, HtmlElement, Rect}; pub use webapi::window_or_worker::IWindowOrWorker; pub use webapi::parent_node::IParentNode; pub use webapi::slotable::ISlotable; pub use webapi::non_element_parent_node::INonElementParentNode; pub use webapi::token_list::TokenList; pub use webapi::node_list::NodeList; pub use webapi::string_map::StringMap; pub use webapi::storage::Storage; pub use webapi::location::Location; pub use webapi::array_buffer::ArrayBuffer; pub use webapi::typed_array::TypedArray; pub use webapi::file::File; pub use webapi::file_reader::{FileReader, FileReaderResult, FileReaderReadyState}; pub use webapi::file_list::FileList; pub use webapi::history::History; pub use webapi::web_socket::{WebSocket, SocketCloseCode, SocketBinaryType, SocketReadyState}; pub use webapi::rendering_context::{RenderingContext, CanvasRenderingContext2d, CanvasGradient, CanvasPattern, CanvasStyle, CompositeOperation, FillRule, ImageData, LineCap, LineJoin, Repetition, TextAlign, TextBaseline, TextMetrics}; pub use webapi::mutation_observer::{MutationObserver, MutationObserverHandle, MutationObserverInit, MutationRecord}; pub use webapi::xml_http_request::{XmlHttpRequest, XhrReadyState, XhrResponseType}; pub use webapi::blob::{IBlob, Blob}; pub use webapi::html_collection::HtmlCollection; pub use webapi::child_node::IChildNode; pub use webapi::gamepad::{Gamepad, GamepadButton, GamepadMappingType}; pub use webapi::touch::{Touch, TouchType}; pub use webapi::selection::Selection; pub use webapi::shadow_root::{ShadowRootMode, ShadowRoot}; pub use webapi::html_elements::SlotContentKind; pub use webapi::form_data::{FormData, FormDataEntry}; pub use webapi::window_or_worker::TimeoutHandle; /// A module containing error types. pub mod error { pub use webapi::dom_exception::{ IDomException, DomException, HierarchyRequestError, IndexSizeError, InvalidAccessError, InvalidStateError, NotFoundError, NotSupportedError, SecurityError, SyntaxError, InvalidCharacterError, AbortError }; pub use webapi::error::{ IError, Error, TypeError }; pub use webapi::rendering_context::{AddColorStopError, DrawImageError, GetImageDataError}; pub use webapi::html_elements::UnknownValueError; pub use webapi::xml_http_request::XhrSetResponseTypeError; } /// A module containing HTML DOM elements. pub mod html_element { pub use webapi::html_elements::ImageElement; pub use webapi::html_elements::InputElement; pub use webapi::html_elements::TextAreaElement; pub use webapi::html_elements::CanvasElement; pub use webapi::html_elements::SelectElement; pub use webapi::html_elements::OptionElement; pub use webapi::html_elements::TemplateElement; pub use webapi::html_elements::SlotElement; } /// A module containing JavaScript DOM events. pub mod event { pub use webapi::event::{ IEvent, IUiEvent, ConcreteEvent, UnloadEvent, BeforeUnloadEvent, FullscreenChangeEvent, EventPhase }; pub use webapi::events::mouse::{ IMouseEvent, ClickEvent, AuxClickEvent, ContextMenuEvent, DoubleClickEvent, MouseDownEvent, MouseUpEvent, MouseMoveEvent, MouseOverEvent, MouseOutEvent, MouseEnterEvent, MouseLeaveEvent, MouseWheelEvent, MouseWheelDeltaMode, MouseButton, MouseButtonsState }; pub use webapi::events::touch::{ ITouchEvent, TouchEvent, TouchMove, TouchLeave, TouchEnter, TouchEnd, TouchCancel, TouchStart, }; pub use webapi::events::pointer::{ IPointerEvent, PointerOverEvent, PointerEnterEvent, PointerDownEvent, PointerMoveEvent, PointerUpEvent, PointerCancelEvent, PointerOutEvent, PointerLeaveEvent, GotPointerCaptureEvent, LostPointerCaptureEvent, PointerLockChangeEvent, PointerLockErrorEvent }; pub use webapi::events::keyboard::{ IKeyboardEvent, KeyPressEvent, KeyDownEvent, KeyUpEvent, KeyboardLocation, ModifierKey }; pub use webapi::events::progress::{ IProgressEvent, ProgressEvent, LoadStartEvent, LoadEndEvent, ProgressLoadEvent, ProgressAbortEvent, ProgressErrorEvent }; pub use webapi::events::socket::{ IMessageEvent, SocketCloseEvent, SocketErrorEvent, SocketOpenEvent, SocketMessageEvent, SocketMessageData }; pub use webapi::events::history::{ HashChangeEvent, PopStateEvent }; pub use webapi::events::dom::{ ChangeEvent, ResourceLoadEvent, ResourceAbortEvent, ResourceErrorEvent, ResizeEvent, ScrollEvent, InputEvent, ReadyStateChangeEvent, SubmitEvent, SelectionChangeEvent }; pub use webapi::events::focus::{ IFocusEvent, FocusEvent, BlurEvent }; pub use webapi::events::gamepad::{ IGamepadEvent, GamepadConnectedEvent, GamepadDisconnectedEvent, }; pub use webapi::events::drag::{ IDragEvent, DragRelatedEvent, DragEvent, DragStartEvent, DragEndEvent, DragEnterEvent, DragLeaveEvent, DragOverEvent, DragExitEvent, DragDropEvent, DataTransfer, EffectAllowed, DropEffect, DataTransferItemList, DataTransferItem, DataTransferItemKind, }; pub use webapi::events::slot::SlotChangeEvent; } #[cfg(feature = "experimental_features_which_may_break_on_minor_version_bumps")] /// APIs related to MIDI. pub mod midi { pub use webapi::midi::{ MidiOptions, MidiAccess, MidiPort, MidiInput, MidiOutput, IMidiPort }; } } /// A module containing stable counterparts to currently /// unstable Rust features. pub mod unstable { pub use webcore::try_from::{ TryFrom, TryInto }; pub use webcore::void::Void; } /// A module containing reexports of all of our interface traits. /// /// You should **only** import its contents through a wildcard, e.g.: `use stdweb::traits::*`. pub mod traits { #[doc(hidden)] pub use super::web::{ // Real interfaces. IEventTarget, INode, IElement, IHtmlElement, IBlob, // Mixins. IWindowOrWorker, IParentNode, INonElementParentNode, IChildNode, ISlotable, }; #[doc(hidden)] pub use super::web::error::{ IDomException, IError }; #[doc(hidden)] pub use super::web::event::{ IEvent, IUiEvent, IMouseEvent, IPointerEvent, IKeyboardEvent, IProgressEvent, IMessageEvent, IFocusEvent, IDragEvent, ITouchEvent, }; #[cfg(feature = "experimental_features_which_may_break_on_minor_version_bumps")] #[doc(hidden)] pub use super::web::midi::IMidiPort; } #[doc(hidden)] pub mod private { #[cfg(all(target_arch = "wasm32", target_vendor = "unknown", target_os = "unknown", not(cargo_web)))] pub extern crate wasm_bindgen; #[cfg(all(target_arch = "wasm32", target_vendor = "unknown", target_os = "unknown", not(cargo_web)))] pub use webcore::ffi::get_module; pub use webcore::ffi::exports::*; pub use webcore::serialization::{ JsSerialize, JsSerializeOwned, SerializedValue }; pub use webcore::newtype::{ IntoNewtype, Newtype }; #[cfg(feature = "serde")] pub use ecosystem::serde::{ to_value, from_value }; pub use webcore::global_arena::ArenaRestorePoint; pub use webcore::global_arena::serialize_value; #[cfg(all(target_arch = "wasm32", target_vendor = "unknown", target_os = "unknown", cargo_web))] pub use stdweb_internal_macros::wasm32_unknown_unknown_js_attr as js_attr; #[cfg(all(target_arch = "wasm32", target_vendor = "unknown", target_os = "unknown", cargo_web))] pub use stdweb_internal_macros::wasm32_unknown_unknown_js_no_return_attr as js_no_return_attr; #[cfg(all(target_arch = "wasm32", target_vendor = "unknown", target_os = "unknown", cargo_web))] pub use stdweb_internal_macros::wasm32_unknown_unknown_js_raw_attr as js_raw_attr; #[cfg(all(target_arch = "wasm32", target_vendor = "unknown", target_os = "unknown", not(cargo_web)))] pub use stdweb_internal_macros::wasm_bindgen_js_attr as js_attr; #[cfg(all(target_arch = "wasm32", target_vendor = "unknown", target_os = "unknown", not(cargo_web)))] pub use stdweb_internal_macros::wasm_bindgen_js_no_return_attr as js_no_return_attr; #[cfg(all(target_arch = "wasm32", target_vendor = "unknown", target_os = "unknown", not(cargo_web)))] pub use stdweb_internal_macros::wasm_bindgen_js_raw_attr as js_raw_attr; #[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))] pub use stdweb_internal_macros::emscripten_js_attr as js_attr; #[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))] pub use stdweb_internal_macros::emscripten_js_no_return_attr as js_no_return_attr; #[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))] pub use stdweb_internal_macros::emscripten_js_raw_attr as js_raw_attr; // This is to prevent an unused_mut warnings in macros, because an `allow` doesn't work apparently? #[allow(dead_code)] #[inline(always)] pub fn noop< T >( _: &mut T ) {} // TODO: Remove this. #[derive(Debug)] pub struct TODO; impl std::fmt::Display for TODO { fn fmt( &self, _: &mut std::fmt::Formatter ) -> Result< (), std::fmt::Error > { unreachable!(); } } impl std::error::Error for TODO { fn description( &self ) -> &str { unreachable!(); } } pub use webcore::value::ConversionError; } stdweb-0.4.20/src/webapi/array_buffer.rs010064400017500001750000000035561331624470200163740ustar0000000000000000use webcore::value::Reference; use webcore::try_from::TryInto; use webcore::value::Value; use webapi::typed_array::TypedArray; use private::TODO; /// The `ArrayBuffer` object is used to represent a generic, fixed-length raw binary data buffer. /// You cannot directly manipulate the contents of an ArrayBuffer; instead, you create an [TypedArray](struct.TypedArray.html) /// to do it. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer) // https://www.ecma-international.org/ecma-262/6.0/#sec-arraybuffer-constructor #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "ArrayBuffer")] pub struct ArrayBuffer( Reference ); impl ArrayBuffer { /// Creates a new `ArrayBuffer` with the given length in bytes. // https://www.ecma-international.org/ecma-262/6.0/#sec-arraybuffer-length pub fn new( length: u64 ) -> Result< Self, TODO > { let length: Value = length.try_into().unwrap(); Ok( js!( return new ArrayBuffer( @{length} ); ).try_into().unwrap() ) } /// Returns the length of the buffer, in bytes. // https://www.ecma-international.org/ecma-262/6.0/#sec-get-arraybuffer.prototype.bytelength pub fn len( &self ) -> u64 { let reference = self.as_ref(); let length = js!( return @{reference}.byteLength; ).try_into().unwrap(); length } } // TODO: Implement for other types. // TODO: Implement slightly more efficiently than going through the TypedArray. impl From< ArrayBuffer > for Vec< u8 > { fn from( buffer: ArrayBuffer ) -> Self { let typed_array: TypedArray< u8 > = buffer.into(); typed_array.into() } } impl< 'a > From< &'a ArrayBuffer > for Vec< u8 > { fn from( buffer: &'a ArrayBuffer ) -> Self { let typed_array: TypedArray< u8 > = buffer.into(); typed_array.into() } } stdweb-0.4.20/src/webapi/blob.rs010064400017500001750000000067561351316303100146420ustar0000000000000000use std::ops::{RangeBounds, Bound}; use webcore::value::Reference; use webcore::try_from::TryInto; use webcore::reference_type::ReferenceType; use webcore::number::Number; use webcore::optional_arg::OptionalArg; // https://w3c.github.io/FileAPI/#ref-for-dfn-slice fn slice_blob< T, U >( blob: &T, range: U, content_type: Option< &str > ) -> Blob where T: IBlob, U: RangeBounds< u64 > { let start: Number = match range.start_bound() { Bound::Included(&n) => n, Bound::Excluded(&n) => n + 1, Bound::Unbounded => 0 }.try_into().unwrap(); let end: OptionalArg< Number > = match range.end_bound() { Bound::Included(&n) => Some(n + 1), Bound::Excluded(&n) => Some(n), Bound::Unbounded => None }.try_into().unwrap(); let content_type: OptionalArg< &str > = content_type.into(); let reference = blob.as_ref(); js! ( return @{reference}.slice(@{start}, @{end}, @{content_type}); ).try_into().unwrap() } /// A blob object represents a file-like object of immutable, raw data. /// Blobs represent data that isn't necessarily in a JavaScript-native format. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Blob) // https://w3c.github.io/FileAPI/#dfn-Blob pub trait IBlob: ReferenceType { /// The size, in bytes, of the data contained in the Blob object. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Blob/size) // https://w3c.github.io/FileAPI/#ref-for-dfn-size%E2%91%A0 fn len( &self ) -> u64 { let reference = self.as_ref(); let length: u64 = js!( return @{reference}.size; ).try_into().unwrap(); length } /// A string indicating the MIME type of the data contained in the `Blob`. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Blob/type) // https://w3c.github.io/FileAPI/#ref-for-dfn-type%E2%91%A0 fn mime( &self ) -> Option< String > { let reference = self.as_ref(); let mime: String = js!( return @{reference}.type; ).try_into().unwrap(); if mime.is_empty() { None } else { Some( mime ) } } /// Create a new `Blob` object containing the data in the specified range of bytes of the /// source `Blob`. /// /// See also [slice_with_content_type](IBlob::slice_with_content_type). /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Blob/slice) fn slice< T >( &self, range: T ) -> Blob where T: RangeBounds { slice_blob(self, range, None) } /// [slice](IBlob::slice) `Blob` with the provided `content_type`. fn slice_with_content_type< T >( &self, range: T, content_type: &str ) -> Blob where T: RangeBounds { slice_blob(self, range, Some(content_type)) } } /// A reference to a JavaScript object which implements the [IBlob](trait.IBlob.html) /// interface. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Blob) // https://w3c.github.io/FileAPI/#dfn-Blob #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "Blob")] pub struct Blob( Reference ); impl IBlob for Blob {} impl Blob { /// Creates a new `Blob`. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Blob/Blob) // https://w3c.github.io/FileAPI/#constructorBlob pub fn new() -> Self { js! ( return new Blob(); ).try_into().unwrap() } } stdweb-0.4.20/src/webapi/child_node.rs010064400017500001750000000014521331624470200160060ustar0000000000000000use webcore::reference_type::ReferenceType; /// The `ChildNode` interface contains methods that are particular to `Node` /// objects that can have a parent. /// /// You most likely don't want to `use` this directly; instead /// you should `use stdweb::traits::*;`. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/ChildNode) // https://dom.spec.whatwg.org/#interface-childnode pub trait IChildNode: ReferenceType { /// The `ChildNode.remove()` method removes the object from the tree it belongs to. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/ChildNode/remove) // https://dom.spec.whatwg.org/#ref-for-dom-childnode-remove fn remove( &self ) { js! { @(no_return) @{self.as_ref()}.remove(); }; } } stdweb-0.4.20/src/webapi/console.rs010064400017500001750000000040311350450674000153560ustar0000000000000000#[doc(hidden)] #[macro_export] macro_rules! __internal_console_unsafe { ( $name:ident ) => {{ $crate::js! { @(no_return) console.$name(); } () }}; ( $name:ident, $( $args:expr ),* ) => {{ $crate::js! { @(no_return) console.$name( $( @{$args} ),* ); } () }}; } /// Calls methods on the JavaScript `console` object. /// /// This should **only** be used for debugging purposes, its behavior is /// **not** standardized: it **will** vary with different browsers /// and Node.js. /// /// The first argument is the name of the `console` method. /// /// The remaining arguments can be anything which can be sent to JavaScript, /// and they do not need to be the same type. /// /// If you want to print things to the console in a standardized way, use /// [`println!`](https://doc.rust-lang.org/std/macro.println.html) instead. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/console) /// /// # Examples /// /// ## log /// /// Print a newline: /// /// ```rust /// console!(log, ""); /// ``` /// /// Print one value: /// /// ```rust /// console!(log, "Hello world!"); /// ``` /// /// Print more than one value: /// /// ```rust /// console!(log, 1, "test", vec![2, 3]); /// ``` /// /// Use [string substitution](https://developer.mozilla.org/en-US/docs/Web/API/console#Using_string_substitutions) to control how the values are printed: /// /// ```rust /// console!(log, "foo: %s bar: %s", vec![1, 2], vec![3, 4]); /// ``` /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Console/log) /// /// ## error /// /// This is exactly the same as `log`, except it prints an error message rather than a normal message. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Console/error) #[macro_export] macro_rules! console { ( log, $( $args:expr ),+ ) => { $crate::__internal_console_unsafe!( log, $( $args ),+ ) }; ( error, $( $args:expr ),+ ) => { $crate::__internal_console_unsafe!( error, $( $args ),+ ) }; } stdweb-0.4.20/src/webapi/cross_origin_setting.rs010064400017500001750000000011551331624470200201530ustar0000000000000000 /// Represents CORS (Cross Origin Resource Sharing) setting for an HTML element. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_settings_attributes) // https://html.spec.whatwg.org/#cors-settings-attribute #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum CrossOriginSetting { /// CORS is not used for this element. None, /// CORS requests for this element will not have the credentials flag set. Anonymous, /// CORS requests for this element will have the credentials flag set; /// this means the request will provide credentials. UseCredentials, } stdweb-0.4.20/src/webapi/date.rs010064400017500001750000001006151331624470200146340ustar0000000000000000use webcore::value::Reference; use webcore::try_from::TryInto; /// [(JavaScript docs)](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Date) /// https://www.ecma-international.org/ecma-262/6.0/#sec-date-constructor #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "Date")] pub struct Date( Reference ); impl Date { /// Creates a JavaScript Date instance that represents a single moment in time. /// Date objects are based on a time value that is the number of milliseconds since 1 January 1970 UTC. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) // https://www.ecma-international.org/ecma-262/6.0/#sec-date-constructor-date pub fn new() -> Self { js!( return new Date(); ).try_into().unwrap() } /// Creates a JavaScript Date instance that represents a single moment in time. /// Date objects are based on a time value that is the number of milliseconds since 1 January 1970 UTC. /// /// year is an integer value representing the year. Values from 0 to 99 map to the years 1900 to 1999. /// month is an integer value representing the month, beginning with 0 for January to 11 for December /// day is an integer value representing the day of the month (normally from 1 to 31) /// hours an integer value representing the minute segment of a time /// seconds an integer value representing the second segment of a time /// milliseconds an integer value representing the millisecond segment of a time /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) // https://www.ecma-international.org/ecma-262/6.0/#sec-date-year-month-date-hours-minutes-seconds-ms pub fn from_datetime(year: i32, month: i32, day: i32, hours: i32, minutes: i32, seconds: i32, milliseconds: i32) -> Self { js!( return new Date(@{year}, @{month}, @{day}, @{hours}, @{minutes}, @{seconds}, @{milliseconds}); ).try_into().unwrap() } /// Creates a JavaScript Date instance that represents a single moment in time. /// Date objects are based on a time value that is the number of milliseconds since 1 January 1970 UTC. /// /// String value representing a date. The string should be in a format recognized by /// the Date.parse() method (IETF-compliant RFC 2822 timestamps and also a version of ISO8601). /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) // https://www.ecma-international.org/ecma-262/6.0/#sec-date-value pub fn from_iso8601(date_string: &str) -> Self { js!( return new Date(@{date_string}); ).try_into().unwrap() } /// Creates a JavaScript Date instance that represents a single moment in time. /// Date objects are based on a time value that is the number of milliseconds since 1 January 1970 UTC. /// /// Integer value representing the number of milliseconds since January 1, 1970, 00:00:00 UTC, /// with leap seconds ignored (Unix Epoch; but consider that most Unix timestamp functions count in seconds). /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) // https://www.ecma-international.org/ecma-262/6.0/#sec-date-value pub fn from_time(now: f64) -> Self { js!( return new Date(@{now}); ).try_into().unwrap() } /// The Date.UTC() method accepts the same parameters as the longest form of the constructor, and /// returns the number of milliseconds in a Date object since January 1, 1970, 00:00:00, universal time. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/UTC) // https://www.ecma-international.org/ecma-262/6.0/#sec-date.utc pub fn utc(year: i32, month: i32, day: i32, hours: i32, minutes: i32, seconds: i32, milliseconds: i32) -> f64 { js!( return Date.UTC(@{year}, @{month}, @{day}, @{hours}, @{minutes}, @{seconds}, @{milliseconds}); ).try_into().unwrap() } /// The Date.parse() method parses a string representation of a date, and returns the number of /// milliseconds since January 1, 1970, 00:00:00 UTC or NaN if the string is unrecognized or, in /// some cases, contains illegal date values (e.g. 2015-02-31). /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) // https://www.ecma-international.org/ecma-262/6.0/#sec-date.parse pub fn parse(date_string: &str) -> f64 { js!( return Date.parse(@{date_string}); ).try_into().unwrap() } /// The Date.now() method returns the number of milliseconds elapsed since 1 January 1970 00:00:00 UTC. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now) // https://www.ecma-international.org/ecma-262/6.0/#sec-date.now pub fn now() -> f64 { js!( return Date.now(); ).try_into().unwrap() } /// The getDate() method returns the day of the month for the specified date according to local time. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getDate) // https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype.getdate pub fn get_date(&self) -> i32 { js!( return @{self}.getDate(); ).try_into().unwrap() } /// The getDay() method returns the day of the week for the specified date according to local time, /// where 0 represents Sunday. For the day of the month see getDate(). /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getDay) // https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype.getday pub fn get_day(&self) -> i32 { js!( return @{self}.getDay(); ).try_into().unwrap() } /// The getFullYear() method returns the year of the specified date according to local time. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getDay) // https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype.getfullyear pub fn get_full_year(&self) -> i32 { js!( return @{self}.getFullYear(); ).try_into().unwrap() } /// The getHours() method returns the hour for the specified date, according to local time. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getHours) // https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype.gethours pub fn get_hours(&self) -> i32 { js!( return @{self}.getHours(); ).try_into().unwrap() } /// The getMilliseconds() method returns the milliseconds in the specified date according to local time. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getMilliseconds) // https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype.getmilliseconds pub fn get_milliseconds(&self) -> i32 { js!( return @{self}.getMilliseconds(); ).try_into().unwrap() } /// The getMinutes() method returns the minutes in the specified date according to local time. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getMinutes) // https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype.getminutes pub fn get_minutes(&self) -> i32 { js!( return @{self}.getMinutes(); ).try_into().unwrap() } /// The getMonth() method returns the month in the specified date according to local time, as a /// zero-based value (where zero indicates the first month of the year). /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getMonth) // https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype.getmonth pub fn get_month(&self) -> i32 { js!( return @{self}.getMonth(); ).try_into().unwrap() } /// The getSeconds() method returns the seconds in the specified date according to local time. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getSeconds) // https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype.getseconds pub fn get_seconds(&self) -> i32 { js!( return @{self}.getSeconds(); ).try_into().unwrap() } /// The getTime() method returns the numeric value corresponding to the time for the specified /// date according to universal time. /// /// getTime() always uses UTC for time representation. For example, a client browser in one timezone, /// getTime() will be the same as a client browser in any other timezone. /// /// You can use this method to help assign a date and time to another Date object. This method is /// functionally equivalent to the valueOf() method. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTime) // https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype.gettime pub fn get_time(&self) -> f64 { js!( return @{self}.getTime(); ).try_into().unwrap() } /// The getTimezoneOffset() method returns the time zone difference, in minutes, from current locale (host system settings) to UTC. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTimezoneOffset) // https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype.gettimezoneoffset pub fn get_timezone_offset(&self) -> i32 { js!( return @{self}.getTimezoneOffset(); ).try_into().unwrap() } /// The getUTCDate() method returns the day (date) of the month in the specified date according to /// universal time. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getUTCDate) // https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype.getutcdate pub fn get_utc_date(&self) -> i32 { js!( return @{self}.getUTCDate(); ).try_into().unwrap() } /// The getUTCDay() method returns the day of the week in the specified date according to universal /// time, where 0 represents Sunday. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getUTCDay) // https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype.getutcday pub fn get_utc_day(&self) -> i32 { js!( return @{self}.getUTCDay(); ).try_into().unwrap() } /// The getUTCFullYear() method returns the year in the specified date according to universal time. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getUTCFullYear) // https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype.getutcfullyear pub fn get_utc_full_year(&self) -> i32 { js!( return @{self}.getUTCFullYear(); ).try_into().unwrap() } /// The getUTCHours() method returns the hours in the specified date according to universal time. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getUTCHours) // https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype.getutchours pub fn get_utc_hours(&self) -> i32 { js!( return @{self}.getUTCHours(); ).try_into().unwrap() } /// The getUTCMilliseconds() method returns the milliseconds in the specified date according to /// universal time. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getUTCMilliseconds) // https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype.getutcmilliseconds pub fn get_utc_milliseconds(&self) -> i32 { js!( return @{self}.getUTCMilliseconds(); ).try_into().unwrap() } /// The getUTCMinutes() method returns the minutes in the specified date according to universal time. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getUTCMinutes) // https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype.getutcminutes pub fn get_utc_minutes(&self) -> i32 { js!( return @{self}.getUTCMinutes(); ).try_into().unwrap() } /// The getUTCMonth() returns the month of the specified date according to universal time, as a /// zero-based value (where zero indicates the first month of the year). /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getUTCMonth) // https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype.getutcmonth pub fn get_utc_month(&self) -> i32 { js!( return @{self}.getUTCMonth(); ).try_into().unwrap() } /// The getUTCSeconds() method returns the seconds in the specified date according to universal time. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getUTCSeconds) // https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype.getutcseconds pub fn get_utc_seconds(&self) -> i32 { js!( return @{self}.getUTCSeconds(); ).try_into().unwrap() } /// The setDate() method sets the day of the Date object relative to the beginning of the currently set month. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/setDate) // https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype.setdate pub fn set_date(&self, date: i32) { js!{ @(no_return) @{self}.setDate(@{date}); } } /// The setFullYear() method sets the full year for a specified date according to local time. Returns new timestamp. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/setFullYear) // https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype.setfullyear pub fn set_full_year(&self, full_year: i32) { js!{ @(no_return) @{self}.setFullYear(@{full_year}); } } /// The setHours() method sets the hours for a specified date according to local time, and returns the number of milliseconds /// since January 1, 1970 00:00:00 UTC until the time represented by the updated Date instance. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/setHours) // https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype.sethours pub fn set_hours(&self, hours: i32) { js!{ @(no_return) @{self}.setHours(@{hours}); } } /// The setMilliseconds() method sets the milliseconds for a specified date according to local time. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/setMilliseconds) // https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype.setmilliseconds pub fn set_milliseconds(&self, milliseconds: i32) { js!{ @(no_return) @{self}.setMilliseconds(@{milliseconds}); } } /// The setMinutes() method sets the minutes for a specified date according to local time. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/setMinutes) // https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype.setminutes pub fn set_minutes(&self, minutes: i32) { js!{ @(no_return) @{self}.setMinutes(@{minutes}); } } /// The setMonth() method sets the month for a specified date according to the currently set year. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/setMonth) // https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype.setmonth pub fn set_month(&self, month: i32) { js!{ @(no_return) @{self}.setMonth(@{month}); } } /// The setSeconds() method sets the seconds for a specified date according to local time. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/setSeconds) // https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype.setseconds pub fn set_seconds(&self, seconds: i32) { js!{ @(no_return) @{self}.setSeconds(@{seconds}); } } /// The setTime() method sets the Date object to the time represented by a number of milliseconds since /// January 1, 1970, 00:00:00 UTC. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/setTime) // https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype.settime pub fn set_time(&self, time: f64) { js!{ @(no_return) @{self}.setTime(@{time}); } } /// The setUTCDate() method sets the day of the month for a specified date according to universal time. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/setUTCDate) // https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype.setutcdate pub fn set_utc_date(&self, date: i32) { js!{ @(no_return) @{self}.setUTCDate(@{date}); } } /// The setUTCFullYear() method sets the full year for a specified date according to universal time. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/setUTCFullYear) // https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype.setutcfullyear pub fn set_utc_full_year(&self, full_year: i32) { js!{ @(no_return) @{self}.setUTCFullYear(@{full_year}); } } /// The setUTCHours() method sets the hour for a specified date according to universal time, and returns the number /// of milliseconds since January 1, 1970 00:00:00 UTC until the time represented by the updated Date instance. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/setUTCHours) // https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype.setutchours pub fn set_utc_hours(&self, hours: i32) { js!{ @(no_return) @{self}.setUTCHours(@{hours}); } } /// The setUTCMilliseconds() method sets the milliseconds for a specified date according to universal time. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/setUTCMilliseconds) // https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype.setutcmilliseconds pub fn set_utc_milliseconds(&self, milliseconds: i32) { js!{ @(no_return) @{self}.setUTCMilliseconds(@{milliseconds}); } } /// The setUTCMinutes() method sets the minutes for a specified date according to universal time. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/setUTCMinutes) // https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype.setutcminutes pub fn set_utc_minutes(&self, minutes: i32) { js!{ @(no_return) @{self}.setUTCMinutes(@{minutes}); } } /// The setUTCMonth() method sets the month for a specified date according to universal time. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/setUTCMonth) // https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype.setutcmonth pub fn set_utc_month(&self, month: i32) { js!{ @(no_return) @{self}.setUTCMonth(@{month}); } } /// The setUTCSeconds() method sets the seconds for a specified date according to universal time. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/setUTCSeconds) // https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype.setutcseconds pub fn set_utc_seconds(&self, seconds: i32) { js!{ @(no_return) @{self}.setUTCSeconds(@{seconds}); } } /// The toDateString() method returns the date portion of a Date object in human readable form in American English. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toUTCString) // https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype.todatestring #[inline] pub fn to_date_string(&self) -> String { js!( return @{self}.toDateString(); ).try_into().unwrap() } /// The toISOString() method returns a string in simplified extended ISO format (ISO 8601), which is always 24 or 27 /// characters long (YYYY-MM-DDTHH:mm:ss.sssZ or ±YYYYYY-MM-DDTHH:mm:ss.sssZ, respectively). The timezone is always zero /// UTC offset, as denoted by the suffix "Z". /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString) // https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype.toisostring #[inline] pub fn to_iso_string(&self) -> String { js!( return @{self}.toISOString(); ).try_into().unwrap() } /// The toJSON() method returns a string representation of the Date object. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toJSON) // https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype.tojson #[inline] pub fn to_json(&self) -> String { js!( return @{self}.toJSON(); ).try_into().unwrap() } /// The toString() method returns a string representing the specified Date object. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toString) // https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype.tostring #[inline] pub fn to_string(&self) -> String { js!( return @{self}.toString(); ).try_into().unwrap() } /// The toTimeString() method returns the time portion of a Date object in human readable form in American English. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toTimeString) // https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype.totimestring #[inline] pub fn to_time_string(&self) -> String { js!( return @{self}.toTimeString(); ).try_into().unwrap() } /// The toUTCString() method converts a date to a string, using the UTC time zone. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toUTCString) // https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype.toutcstring #[inline] pub fn to_utc_string(&self) -> String { js!( return @{self}.toUTCString(); ).try_into().unwrap() } /// The valueOf() method returns the primitive value of a Date object. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/valueOf) // https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype.valueof pub fn value_of(&self) -> f64 { js!( return @{self}.valueOf(); ).try_into().unwrap() } } #[cfg(test)] mod tests { use super::*; #[test] fn test_date_now() { let now = Date::now(); assert!( now > 0.0 ); } #[test] fn test_date_utc() { let now = Date::utc(96, 1, 2, 3, 4, 5, 0); assert_eq!(now, 823230245000.0); let now = Date::utc(0, 0, 0, 0, 0, 0, 0); assert_eq!(now, -2209075200000.0); } #[test] fn test_date_parse() { let now = Date::parse("01 Jan 1970 00:00:00 GMT"); assert_eq!(now, 0.0); let now = Date::parse("04 Dec 1995 00:12:00 GMT"); assert_eq!(now, 818035920000.0); } #[test] fn test_date_get_date() { let now = Date::from_iso8601("August 19, 1975 23:15:30"); assert_eq!( now.get_date(), 19); } #[test] fn test_date_get_day() { let now = Date::from_iso8601("August 19, 1975 23:15:30"); assert_eq!(now.get_day(), 2); } #[test] fn test_date_get_full_year() { let now = Date::from_iso8601("August 19, 75 23:15:30"); assert_eq!(now.get_full_year(), 1975); } #[test] fn test_date_get_hours() { let now = Date::from_iso8601("August 19, 1975 23:15:30"); assert_eq!(now.get_hours(), 23); } #[test] fn test_date_get_milliseconds() { let now = Date::from_iso8601("August 19, 1975 23:15:30"); now.set_milliseconds(123); assert_eq!(now.get_milliseconds(), 123); } #[test] fn test_date_get_minutes() { let now = Date::from_iso8601("August 19, 1975 23:15:30"); assert_eq!(now.get_minutes(), 15); } #[test] fn test_date_get_month() { let now = Date::from_iso8601("August 19, 1975 23:15:30"); assert_eq!(now.get_month(), 7); } #[test] fn test_date_get_seconds() { let now = Date::from_iso8601("August 19, 1975 23:15:30"); assert_eq!(now.get_seconds(), 30); } #[test] fn test_date_get_time() { let now = Date::from_iso8601("July 20, 69 00:20:18 GMT+00:00"); assert_eq!(now.get_time(), -14254782000.0); } #[test] fn test_date_get_timezone_offset() { // this is impossible to test like this, since this function depends on local time only. // and there is no easy way to mock the system time, so the only real thing to check // is that two dates return the same timezone offset. let t1 = Date::from_iso8601("August 19, 1975 23:15:30 GMT+07:00"); let t2 = Date::from_iso8601("August 19, 1975 23:15:30 GMT-02:00"); assert_eq!(t1.get_timezone_offset(), t2.get_timezone_offset()); } #[test] fn test_date_get_utc_date() { let now = Date::from_iso8601("August 19, 1975 23:15:30 GMT+11:00"); assert_eq!(now.get_utc_date(), 19); let now = Date::from_iso8601("August 19, 1975 23:15:30 GMT-11:00"); assert_eq!(now.get_utc_date(), 20); } #[test] fn test_date_get_utc_day() { let now = Date::from_iso8601("August 19, 1975 23:15:30 GMT+11:00"); assert_eq!( now.get_utc_day(), 2 ); let now = Date::from_iso8601("August 19, 1975 23:15:30 GMT-11:00"); assert_eq!( now.get_utc_day(), 3 ); } #[test] fn test_date_get_utc_full_year() { let now = Date::from_iso8601("December 31, 1975 23:15:30 GMT+11:00"); assert_eq!(now.get_utc_full_year(), 1975 ); let now = Date::from_iso8601("December 31, 1975 23:15:30 GMT-11:00"); assert_eq!(now.get_utc_full_year(), 1976 ); } #[test] fn test_date_get_utc_milliseconds() { let now = Date::from_iso8601("August 19, 1975 23:15:30"); now.set_milliseconds(123); assert_eq!(now.get_utc_milliseconds(), 123); } #[test] fn test_date_get_utc_minutes() { let now = Date::from_iso8601("August 19, 1975 23:15:30"); assert_eq!(now.get_utc_minutes(), 15); } #[test] fn test_date_get_utc_month() { let now = Date::from_iso8601("December 31, 1975 23:15:30 GMT+11:00"); assert_eq!(now.get_utc_month(), 11); let now = Date::from_iso8601("December 31, 1975 23:15:30 GMT-11:00"); assert_eq!(now.get_utc_month(), 0); } #[test] fn test_date_set_date() { let now = Date::from_iso8601("August 19, 1975 23:15:30"); now.set_date(3); assert_eq!(now.get_date(), 3); } #[test] fn test_date_set_full_year() { let now = Date::from_iso8601("August 19, 1975 23:15:30"); now.set_full_year(1969); assert_eq!(now.get_full_year(), 1969); } #[test] fn test_date_set_hours() { let now = Date::from_iso8601("August 19, 1975 23:15:30"); now.set_hours(15); assert_eq!(now.get_hours(), 15); } #[test] fn test_date_set_milliseconds() { let now = Date::from_iso8601("August 19, 1975 23:15:30"); now.set_milliseconds(123); assert_eq!(now.get_milliseconds(), 123); } #[test] fn test_date_set_minutes() { let now = Date::from_iso8601("August 19, 1975 23:15:30"); now.set_minutes(42); assert_eq!(now.get_minutes(), 42); } #[test] fn test_date_set_month() { let now = Date::from_iso8601("August 19, 1975 23:15:30"); now.set_month(9); assert_eq!(now.get_month(), 9); } #[test] fn test_date_set_seconds() { let now = Date::from_iso8601("August 19, 1975 23:15:30"); now.set_seconds(59); assert_eq!(now.get_seconds(), 59); } #[test] fn test_date_set_time() { let now = Date::from_iso8601("August 19, 1975 23:15:30"); now.set_time(818035920000.0); assert_eq!(now.to_utc_string(), "Mon, 04 Dec 1995 00:12:00 GMT"); } #[test] fn test_date_set_utc_date() { let now = Date::from_iso8601("August 19, 1975 23:15:30"); now.set_utc_date(3); assert_eq!(now.get_utc_date(), 3); } #[test] fn test_date_set_utc_full_year() { let now = Date::from_iso8601("August 19, 1975 23:15:30"); now.set_utc_full_year(1969); assert_eq!(now.get_utc_full_year(), 1969); } #[test] fn test_date_set_utc_hours() { let now = Date::from_iso8601("August 19, 1975 23:15:30"); now.set_utc_hours(15); assert_eq!(now.get_utc_hours(), 15); } #[test] fn test_date_set_utc_milliseconds() { let now = Date::from_iso8601("August 19, 1975 23:15:30"); now.set_utc_milliseconds(123); assert_eq!(now.get_utc_milliseconds(), 123); } #[test] fn test_date_set_utc_minutes() { let now = Date::from_iso8601("August 19, 1975 23:15:30"); now.set_utc_minutes(42); assert_eq!(now.get_utc_minutes(), 42); } #[test] fn test_date_set_utc_month() { let now = Date::from_iso8601("August 19, 1975 23:15:30"); now.set_utc_month(9); assert_eq!(now.get_utc_month(), 9); } #[test] fn test_date_set_utc_seconds() { let now = Date::from_iso8601("August 19, 1975 23:15:30"); now.set_utc_seconds(59); assert_eq!(now.get_utc_seconds(), 59); } #[test] fn test_date_to_date_string() { let now = Date::from_datetime(1993, 6, 28, 14, 39, 7, 0); assert_eq!(now.to_date_string(), "Wed Jul 28 1993"); } #[test] fn test_date_to_iso_string() { let now = Date::from_iso8601("05 October 2011 14:48 UTC"); assert_eq!(now.to_iso_string(), "2011-10-05T14:48:00.000Z"); } #[test] fn test_date_to_json() { let now = Date::from_iso8601("August 19, 1975 23:15:30 UTC"); assert_eq!(now.to_iso_string(), "1975-08-19T23:15:30.000Z"); } #[test] fn test_date_to_time_string() { // not easy to test this due to time-zones } #[test] fn test_date_to_utc_string() { let now = Date::from_time(Date::utc(96, 1, 2, 3, 4, 5, 0)); assert_eq!(now.to_utc_string(), "Fri, 02 Feb 1996 03:04:05 GMT"); } #[test] fn test_date_value_of() { let now = Date::from_time(Date::utc(96, 1, 2, 3, 4, 5, 0)); assert_eq!(now.value_of(), 823230245000.0); } }stdweb-0.4.20/src/webapi/document.rs010064400017500001750000000256241354024445100155430ustar0000000000000000use webcore::value::{Reference, Value}; use webcore::try_from::{TryInto, TryFrom}; use webcore::promise::{Promise, TypedPromise}; use webapi::error::TypeError; use webapi::event_target::{IEventTarget, EventTarget}; use webapi::node::{INode, Node, CloneKind}; use webapi::element::Element; use webapi::html_element::HtmlElement; use webapi::document_fragment::DocumentFragment; use webapi::text_node::TextNode; use webapi::location::Location; use webapi::parent_node::IParentNode; use webapi::non_element_parent_node::INonElementParentNode; use webapi::dom_exception::{InvalidCharacterError, NamespaceError, NotSupportedError}; /// The `Document` interface represents any web page loaded in the browser and /// serves as an entry point into the web page's content, which is the DOM tree. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Document) // https://dom.spec.whatwg.org/#document #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "Document")] #[reference(subclass_of(EventTarget, Node))] pub struct Document( Reference ); error_enum_boilerplate! { CreateElementNsError, InvalidCharacterError, NamespaceError } impl IEventTarget for Document {} impl IParentNode for Document {} impl INode for Document {} impl INonElementParentNode for Document {} /// A global instance of [Document](struct.Document.html). /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Document) pub fn document() -> Document { unsafe { js!( return document; ).into_reference_unchecked() }.unwrap() } impl Document { /// In an HTML document, the Document.createDocumentFragment() method creates a /// new empty DocumentFragment. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Document/createDocumentFragment) // https://dom.spec.whatwg.org/#ref-for-dom-document-createdocumentfragment pub fn create_document_fragment( &self ) -> DocumentFragment { unsafe { js!( return @{self}.createDocumentFragment(); ).into_reference_unchecked().unwrap() } } /// In an HTML document, the Document.createElement() method creates the HTML /// element specified by `tag`, or an HTMLUnknownElement if `tag` isn't /// recognized. In other documents, it creates an element with a null namespace URI. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Document/createElement) // https://dom.spec.whatwg.org/#ref-for-dom-document-createelement pub fn create_element( &self, tag: &str ) -> Result< Element, InvalidCharacterError > { js_try!( return @{self}.createElement( @{tag} ); ).unwrap() } /// Creates an element with the specified namespace URI and qualified name. /// To create an element without specifying a namespace URI, use the `createElement` method. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Document/createElementNS) // https://dom.spec.whatwg.org/#ref-for-dom-document-createelementns pub fn create_element_ns( &self, namespace_uri: &str, tag: &str ) -> Result< Element, CreateElementNsError > { js_try!( return @{self}.createElementNS( @{namespace_uri}, @{tag} ); ).unwrap() } /// Creates a new text node. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Document/createTextNode) // https://dom.spec.whatwg.org/#ref-for-dom-document-createtextnode pub fn create_text_node( &self, text: &str ) -> TextNode { unsafe { js!( return @{self}.createTextNode( @{text} ); ).into_reference_unchecked().unwrap() } } /// Returns a [Location](struct.Location.html) object which contains /// information about the URL of the document and provides methods /// for changing that URL and loading another URL. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Document/location) // https://html.spec.whatwg.org/#the-document-object:dom-document-location pub fn location( &self ) -> Option< Location > { unsafe { js!( return @{self}.location; ).into_reference_unchecked() } } /// Returns the `` or `` node of the current document, or null if no such element exists. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Document/body) // https://html.spec.whatwg.org/#the-document-object:dom-document-body pub fn body( &self ) -> Option< HtmlElement > { unsafe { js!( return @{self}.body; ).into_reference_unchecked() } } /// Returns the `` element of the current document. If there are more than one `` /// elements, the first one is returned. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Document/head) // https://html.spec.whatwg.org/#the-document-object:dom-document-head pub fn head( &self ) -> Option< HtmlElement > { unsafe { js!( return @{self}.head; ).into_reference_unchecked() } } /// Gets the title of the document. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Document/title) // https://html.spec.whatwg.org/#the-document-object:document.title pub fn title( &self ) -> String { js!( return @{self}.title; ).try_into().unwrap() } /// Sets the title of the document. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Document/title) // https://html.spec.whatwg.org/#the-document-object:document.title pub fn set_title( &self, title: &str ) { js!( @(no_return) @{self}.title = @{title}; ); } /// Returns the Element that is the root element of the document (for example, the `` /// element for HTML documents). /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Document/documentElement) // https://dom.spec.whatwg.org/#ref-for-dom-document-documentelement pub fn document_element( &self ) -> Option< Element > { js!( return @{self}.documentElement; ).try_into().unwrap() } /// Returns the Element that the pointer is locked to, if it is locked to any /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DocumentOrShadowRoot/pointerLockElement) // https://w3c.github.io/pointerlock/#dom-documentorshadowroot-pointerlockelement pub fn pointer_lock_element( &self ) -> Option< Element > { let value = js!( return @{self}.pointerLockElement; ); match value { Value::Null | Value::Undefined => None, Value::Reference(reference) => Some(reference.try_into().unwrap()), _ => unreachable!() } } /// Exit the pointer lock on the current element /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Document/exitPointerLock) // https://w3c.github.io/pointerlock/#dom-document-exitpointerlock pub fn exit_pointer_lock( &self ) { js!( @(no_return) @{self}.exitPointerLock(); ); } /// Import node from another document /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Document/importNode) // https://dom.spec.whatwg.org/#ref-for-dom-document-importnode pub fn import_node( &self, n: &N, kind: CloneKind ) -> Result { let deep = match kind { CloneKind::Deep => true, CloneKind::Shallow => false, }; js_try!( return @{self}.importNode( @{n.as_ref()}, @{deep} ); ).unwrap() } /// Check if the fullscreen API is enabled /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Document/fullscreenEnabled) // https://fullscreen.spec.whatwg.org/#ref-for-dom-document-fullscreenenabled pub fn fullscreen_enabled( &self ) -> bool { match js!( return @{self}.fullscreenEnabled; ) { Value::Bool(value) => value, _ => false, // if the variable is not set as a bool, then assume fullscreen is not supported } } /// Get the current fullscreen element, or None if there is nothing fullscreen /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DocumentOrShadowRoot/fullscreenElement) // https://fullscreen.spec.whatwg.org/#ref-for-dom-document-fullscreenelement pub fn fullscreen_element( &self ) -> Option { Some(js!( return @{self}.fullscreenElement; ) .into_reference()? .downcast::()?) } /// Request the page return from fullscreen mode to a normal state /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Document/exitFullscreen) // https://fullscreen.spec.whatwg.org/#dom-document-exitfullscreen #[cfg(feature = "experimental_features_which_may_break_on_minor_version_bumps")] pub fn exit_fullscreen(&self) -> TypedPromise<(), TypeError> { let promise: Promise = js!( return @{self}.exitFullscreen(); ) .try_into().unwrap(); TypedPromise::new( promise ) } } #[cfg(all(test, feature = "web_test"))] mod web_tests { use super::*; use webapi::node::{Node, INode, CloneKind}; use webapi::html_elements::TemplateElement; use webapi::html_element::HtmlElement; #[test] fn test_create_element_invalid_character() { match document().create_element("-invalid tag") { Err(InvalidCharacterError{..}) => (), v => panic!("expected InvalidCharacterError, got {:?}", v), } } #[test] fn test_create_element_ns_invalid_character() { match document().create_element_ns("", "-invalid tag") { Err(CreateElementNsError::InvalidCharacterError(_)) => (), v => panic!("expected InvalidCharacterError, got {:?}", v), } } #[test] fn test_create_element_ns_namespace_error() { match document().create_element_ns("", "illegal_prefix:svg") { Err(CreateElementNsError::NamespaceError(_)) => (), v => panic!("expected NamespaceError, got {:?}", v), } } #[test] fn test_import_node() { let document = document(); let tpl: TemplateElement = Node::from_html("") .unwrap() .try_into() .unwrap(); let n = document.import_node(&tpl.content(), CloneKind::Deep).unwrap(); let child_nodes = n.child_nodes(); assert_eq!(child_nodes.len(), 1); let span_element: HtmlElement = child_nodes.iter().next().unwrap().try_into().unwrap(); assert_eq!(span_element.node_name(), "SPAN"); assert_eq!(js!( return @{span_element}.innerHTML; ), "aaabbbcccddd"); } } stdweb-0.4.20/src/webapi/document_fragment.rs010064400017500001750000000012321347032716600174220ustar0000000000000000use webcore::value::Reference; use webapi::event_target::{IEventTarget, EventTarget}; use webapi::node::{INode, Node}; use webapi::parent_node::IParentNode; /// A reference to a JavaScript object DocumentFragment. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DocumentFragment) // https://dom.spec.whatwg.org/#documentfragment #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "DocumentFragment")] #[reference(subclass_of(EventTarget, Node))] pub struct DocumentFragment( Reference ); impl IEventTarget for DocumentFragment {} impl INode for DocumentFragment {} impl IParentNode for DocumentFragment {} stdweb-0.4.20/src/webapi/dom_exception.rs010064400017500001750000000156151337463116100165640ustar0000000000000000use webcore::value::Reference; use webapi::error::{IError, Error}; /// The `IDomException` interface represents an abnormal event which occurs as the result of /// calling a web API. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DOMException) // https://heycam.github.io/webidl/#idl-DOMException pub trait IDomException: IError {} /// A reference to a JavaScript `DOMException` object. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DOMException) // https://heycam.github.io/webidl/#idl-DOMException #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "DOMException")] #[reference(subclass_of(Error))] pub struct DomException( Reference ); impl IError for DomException {} impl IDomException for DomException {} error_boilerplate! { DomException } /// Occurs when an operation would result in an incorrect node tree. // https://heycam.github.io/webidl/#hierarchyrequesterror #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(subclass_of(Error, DomException))] pub struct HierarchyRequestError( Reference ); impl IError for HierarchyRequestError {} impl IDomException for HierarchyRequestError {} error_boilerplate! { HierarchyRequestError, dom_exception = "HierarchyRequestError" } /// Occurs when an object does not support an operation or argument. // https://heycam.github.io/webidl/#invalidaccesserror #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(subclass_of(Error, DomException))] pub struct InvalidAccessError( Reference ); impl IError for InvalidAccessError {} impl IDomException for InvalidAccessError {} error_boilerplate! { InvalidAccessError, dom_exception = "InvalidAccessError" } /// Occurs when the object can not be modified. // https://heycam.github.io/webidl/#nomodificationallowederror #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(subclass_of(Error, DomException))] pub struct NoModificationAllowedError( Reference ); impl IError for NoModificationAllowedError {} impl IDomException for NoModificationAllowedError {} error_boilerplate! { NoModificationAllowedError, dom_exception = "NoModificationAllowedError" } /// Occurs when the specified object cannot be found. // https://heycam.github.io/webidl/#notfounderror #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(subclass_of(Error, DomException))] pub struct NotFoundError( Reference ); impl IError for NotFoundError {} impl IDomException for NotFoundError {} error_boilerplate! { NotFoundError, dom_exception = "NotFoundError" } /// Occurs when the requested operation is insecure. // https://heycam.github.io/webidl/#securityerror #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(subclass_of(Error, DomException))] pub struct SecurityError( Reference ); impl IError for SecurityError {} impl IDomException for SecurityError {} error_boilerplate! { SecurityError, dom_exception = "SecurityError" } /// Occurs when an argument does not match the expected pattern. // https://heycam.github.io/webidl/#syntaxerror #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(subclass_of(Error, DomException))] pub struct SyntaxError( Reference ); impl IError for SyntaxError {} impl IDomException for SyntaxError {} error_boilerplate! { SyntaxError, dom_exception = "SyntaxError" } /// Occurs when an argument is out of range. // https://heycam.github.io/webidl/#indexsizeerror #[derive(Clone, Debug, ReferenceType)] #[reference(subclass_of(Error, DomException))] pub struct IndexSizeError( Reference ); impl IError for IndexSizeError {} impl IDomException for IndexSizeError {} error_boilerplate! { IndexSizeError, dom_exception = "IndexSizeError" } /// Occurs when an object is in an invalid state. // https://heycam.github.io/webidl/#invalidstateerror #[derive(Clone, Debug, ReferenceType)] #[reference(subclass_of(Error, DomException))] pub struct InvalidStateError( Reference ); impl IError for InvalidStateError {} impl IDomException for InvalidStateError {} error_boilerplate! { InvalidStateError, dom_exception = "InvalidStateError" } /// Used to indicate an unsuccessful operation when none of the other NativeError objects are an appropriate indication of the failure cause. // https://heycam.github.io/webidl/#notsupportederror #[derive(Clone, Debug, ReferenceType)] #[reference(subclass_of(Error, DomException))] pub struct NotSupportedError( Reference ); impl IError for NotSupportedError {} impl IDomException for NotSupportedError {} error_boilerplate! { NotSupportedError, dom_exception = "NotSupportedError" } /// Used to indicate the string contains one or more characters which are invalid. // https://heycam.github.io/webidl/#invalidcharactererror #[derive(Clone, Debug, ReferenceType)] #[reference(subclass_of(Error, DomException))] pub struct InvalidCharacterError( Reference ); impl IError for InvalidCharacterError {} impl IDomException for InvalidCharacterError {} error_boilerplate! { InvalidCharacterError, dom_exception = "InvalidCharacterError" } /// Used to indicate that a pointer id passed as an argument was for some reason invalid. // https://w3c.github.io/pointerevents/#extensions-to-the-element-interface #[derive(Clone, Debug, ReferenceType)] #[reference(subclass_of(Error, DomException))] pub struct InvalidPointerId( Reference ); impl IError for InvalidPointerId {} impl IDomException for InvalidPointerId {} error_boilerplate! { InvalidPointerId, dom_exception = "InvalidPointerId" } /// Used to indicate that the operation was aborted. // https://heycam.github.io/webidl/#aborterror #[derive(Clone, Debug, ReferenceType)] #[reference(subclass_of(Error, DomException))] pub struct AbortError( Reference ); impl IError for AbortError {} impl IDomException for AbortError {} error_boilerplate! { AbortError, dom_exception = "AbortError" } /// Indicates an xml namespace-related feature was used incorrectly. // https://heycam.github.io/webidl/#namespaceerror #[derive(Clone, Debug, ReferenceType)] #[reference(subclass_of(Error, DomException))] pub struct NamespaceError( Reference ); impl IError for NamespaceError {} impl IDomException for NamespaceError {} error_boilerplate! { NamespaceError, dom_exception = "NamespaceError" } #[cfg(all(test, feature = "web_test"))] mod test { use super::*; use webcore::try_from::TryInto; fn new_dom_exception(message: &str, name: &str) -> DomException { js!( return new DOMException(@{message}, @{name}); ).try_into().unwrap() } #[test] fn test_error() { let name = "HierarchyRequestError"; // Successful downcast. let err: DomException = new_dom_exception("foo", name); let err: HierarchyRequestError = err.try_into().expect("Expected HierarchyRequestError"); assert_eq!(err.name(), name); // Failed downcast. let err: DomException = new_dom_exception("foo", name); let err: Result = err.try_into(); assert!(err.is_err()); } } stdweb-0.4.20/src/webapi/element.rs010064400017500001750000000414241354024445100153520ustar0000000000000000use webcore::value::Reference; use webcore::try_from::{TryFrom, TryInto}; use webcore::promise::{Promise, TypedPromise}; use webapi::error::TypeError; use webapi::dom_exception::{InvalidCharacterError, InvalidPointerId, NoModificationAllowedError, SyntaxError}; use webapi::event_target::{IEventTarget, EventTarget}; use webapi::node::{INode, Node}; use webapi::token_list::TokenList; use webapi::parent_node::IParentNode; use webapi::child_node::IChildNode; use webapi::slotable::ISlotable; use webapi::shadow_root::{ShadowRootMode, ShadowRoot}; use webapi::dom_exception::{NotSupportedError, InvalidStateError}; error_enum_boilerplate! { AttachShadowError, NotSupportedError, InvalidStateError } /// The `IElement` interface represents an object of a [Document](struct.Document.html). /// This interface describes methods and properties common to all /// kinds of elements. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element) // https://dom.spec.whatwg.org/#element pub trait IElement: INode + IParentNode + IChildNode + ISlotable { /// The Element.namespaceURI read-only property returns the namespace URI /// of the element, or null if the element is not in a namespace. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/namespaceURI) // https://dom.spec.whatwg.org/#ref-for-dom-element-namespaceuri fn namespace_uri( &self ) -> Option< String > { js!( return @{self.as_ref()}.namespaceURI; ).try_into().unwrap() } /// The Element.classList is a read-only property which returns a live /// [TokenList](struct.TokenList.html) collection of the class attributes /// of the element. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/classList) // https://dom.spec.whatwg.org/#ref-for-dom-element-classlist fn class_list( &self ) -> TokenList { unsafe { js!( return @{self.as_ref()}.classList; ).into_reference_unchecked().unwrap() } } /// The Element.hasAttribute() method returns a Boolean value indicating whether /// the specified element has the specified attribute or not. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/hasAttribute) // https://dom.spec.whatwg.org/#ref-for-dom-element-hasattribute fn has_attribute( &self, name: &str ) -> bool { js!( return @{self.as_ref()}.hasAttribute( @{name} ); ).try_into().unwrap() } /// Element.getAttribute() returns the value of a specified attribute on the element. /// If the given attribute does not exist, the value returned will either be /// null or "" (the empty string); /// /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/getAttribute) // https://dom.spec.whatwg.org/#ref-for-dom-element-getattribute fn get_attribute( &self, name: &str ) -> Option< String > { js!( return @{self.as_ref()}.getAttribute( @{name} ); ).try_into().unwrap() } /// Sets the value of an attribute on the specified element. If the attribute already /// exists, the value is updated; otherwise a new attribute is added with the /// specified name and value. /// /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/setAttribute) // https://dom.spec.whatwg.org/#ref-for-dom-element-setattribute fn set_attribute( &self, name: &str, value: &str ) -> Result< (), InvalidCharacterError > { js_try!( return @{self.as_ref()}.setAttribute( @{name}, @{value} ); ).unwrap() } /// Gets the the number of pixels that an element's content is scrolled vertically. /// /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollTop) // https://drafts.csswg.org/cssom-view/#ref-for-dom-element-scrolltop%E2%91%A0 fn scroll_top( &self ) -> f64 { js!( return @{self.as_ref()}.scrollTop; ).try_into().unwrap() } /// Sets the the number of pixels that an element's content is scrolled vertically. /// /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollTop) // https://drafts.csswg.org/cssom-view/#ref-for-dom-element-scrolltop%E2%91%A0 fn set_scroll_top( &self, value: f64 ) { js! { @(no_return) @{self.as_ref()}.scrollTop = @{value}; } } /// Gets the the number of pixels that an element's content is scrolled to the left. /// /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollLeft) // https://drafts.csswg.org/cssom-view/#ref-for-dom-element-scrollleft%E2%91%A0 fn scroll_left( &self ) -> f64 { js!( return @{self.as_ref()}.scrollLeft; ).try_into().unwrap() } /// Sets the the number of pixels that an element's content is scrolled to the left. /// /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollLeft) // https://drafts.csswg.org/cssom-view/#ref-for-dom-element-scrollleft%E2%91%A0 fn set_scroll_left( &self, value: f64 ) { js! { @(no_return) @{self.as_ref()}.scrollLeft = @{value}; } } /// Element.getAttributeNames() returns the attribute names of the element /// as an Array of strings. If the element has no attributes it returns an empty array. /// /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/getAttributeNames) // https://dom.spec.whatwg.org/#ref-for-dom-element-getattributenames fn get_attribute_names( &self ) -> Vec { js!( return @{self.as_ref()}.getAttributeNames(); ).try_into().unwrap() } /// Element.removeAttribute removes an attribute from the specified element. /// /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/removeAttribute) // https://dom.spec.whatwg.org/#ref-for-dom-element-removeattribute fn remove_attribute( &self, name: &str ) { js! { @(no_return) @{self.as_ref()}.removeAttribute( @{name} ); } } /// The Element.hasAttributes() method returns Boolean value, indicating if /// the current element has any attributes or not. /// /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/hasAttributes) // https://dom.spec.whatwg.org/#ref-for-dom-element-hasattributes fn has_attributes( &self ) -> bool { js!( return @{self.as_ref()}.hasAttributes(); ).try_into().unwrap() } /// Returns the closest ancestor of the element (or the element itself) which matches the selectors /// given in parameter. If there isn't such an ancestor, it returns /// `None`. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/closest) // https://dom.spec.whatwg.org/#ref-for-dom-element-closest fn closest( &self, selectors: &str) -> Result, SyntaxError> { js_try!( return @{self.as_ref()}.closest(@{selectors}); ).unwrap() } /// Designates a specific element as the capture target of future pointer events. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/setPointerCapture) // https://w3c.github.io/pointerevents/#dom-element-setpointercapture #[inline] fn set_pointer_capture( &self, pointer_id: i32 ) -> Result< (), InvalidPointerId > { js_try!( return @{self.as_ref()}.setPointerCapture( @{pointer_id} ); ).unwrap() } /// Releases pointer capture that was previously set for a specific pointer /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/releasePointerCapture) // https://w3c.github.io/pointerevents/#dom-element-releasepointercapture #[inline] fn release_pointer_capture( &self, pointer_id: i32 ) -> Result< (), InvalidPointerId > { js_try!( return @{self.as_ref()}.releasePointerCapture( @{pointer_id} ); ).unwrap() } /// Returns a boolean indicating if the element has captured the specified pointer /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/hasPointerCapture) // https://w3c.github.io/pointerevents/#dom-element-haspointercapture #[inline] fn has_pointer_capture( &self, pointer_id: i32 ) -> bool { js!( return @{self.as_ref()}.hasPointerCapture( @{pointer_id} ); ).try_into().unwrap() } /// Insert nodes from HTML fragment into specified position. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML) // https://w3c.github.io/DOM-Parsing/#widl-Element-insertAdjacentHTML-void-DOMString-position-DOMString-text fn insert_adjacent_html( &self, position: InsertPosition, html: &str ) -> Result<(), InsertAdjacentError> { js_try!( @(no_return) @{self.as_ref()}.insertAdjacentHTML( @{position.as_str()}, @{html} ); ).unwrap() } /// Insert nodes from HTML fragment before element. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML) fn insert_html_before( &self, html: &str ) -> Result<(), InsertAdjacentError> { self.insert_adjacent_html(InsertPosition::BeforeBegin, html) } /// Insert nodes from HTML fragment as the first children of the element. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML) fn prepend_html( &self, html: &str ) -> Result<(), InsertAdjacentError> { self.insert_adjacent_html(InsertPosition::AfterBegin, html) } /// Insert nodes from HTML fragment as the last children of the element. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML) fn append_html( &self, html: &str ) -> Result<(), InsertAdjacentError> { self.insert_adjacent_html(InsertPosition::BeforeEnd, html) } /// Insert nodes from HTML fragment after element. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML) fn insert_html_after( &self, html: &str ) -> Result<(), InsertAdjacentError> { self.insert_adjacent_html(InsertPosition::AfterEnd, html) } /// The slot property of the Element interface returns the name of the shadow DOM /// slot the element is inserted in. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/slot) // https://dom.spec.whatwg.org/#ref-for-dom-element-slot fn slot( &self ) -> String { js!( return @{self.as_ref()}.slot; ).try_into().unwrap() } /// Attach a shadow DOM tree to the specified element and returns a reference to its `ShadowRoot`. /// It returns a shadow root if successfully attached or `None` if the element cannot be attached. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/attachShadow) // https://dom.spec.whatwg.org/#ref-for-dom-element-attachshadow fn attach_shadow( &self, mode: ShadowRootMode ) -> Result { js_try!( return @{self.as_ref()}.attachShadow( { mode: @{mode.as_str()}} ) ).unwrap() } /// Returns the shadow root of the current element or `None`. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/shadowRoot) // https://dom.spec.whatwg.org/#ref-for-dom-element-shadowroot fn shadow_root( &self ) -> Option { unsafe { js!( return @{self.as_ref()}.shadowRoot; ).into_reference_unchecked() } } /// Request this element and its children be made fullscreen /// /// Note: this may only be called during a user interaction. /// Not all elements may be full-screened, see JS docs for details. /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/requestFullscreen) // https://fullscreen.spec.whatwg.org/#ref-for-dom-element-requestfullscreen #[cfg(feature = "experimental_features_which_may_break_on_minor_version_bumps")] fn request_fullscreen( &self ) -> TypedPromise<(), TypeError> { let promise: Promise = js!( return @{self.as_ref()}.requestFullscreen(); ) .try_into().unwrap(); TypedPromise::new( promise ) } } /// A reference to a JavaScript object which implements the [IElement](trait.IElement.html) /// interface. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element) // https://dom.spec.whatwg.org/#element #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "Element")] #[reference(subclass_of(EventTarget, Node))] pub struct Element( Reference ); impl IEventTarget for Element {} impl INode for Element {} impl IElement for Element {} impl< T: IElement > IParentNode for T {} impl< T: IElement > IChildNode for T {} impl< T: IElement > ISlotable for T {} #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum InsertPosition { /// Insert into the parent directly before the reference element. BeforeBegin, /// Insert at the start of the reference element. AfterBegin, /// Insert at the end of the reference element. BeforeEnd, /// Insert into the parent directly after the reference element. AfterEnd, } /// Errors thrown by `Element::insert_adjacent_html`. error_enum_boilerplate! { InsertAdjacentError, NoModificationAllowedError, SyntaxError } impl InsertPosition { fn as_str(&self) -> &str { match *self { InsertPosition::BeforeBegin => "beforebegin", InsertPosition::AfterBegin => "afterbegin", InsertPosition::BeforeEnd => "beforeend", InsertPosition::AfterEnd => "afterend", } } } #[cfg(all(test, feature = "web_test"))] mod tests { use super::*; use webapi::document::document; use webapi::shadow_root::ShadowRootMode; fn div() -> Element { js!( return document.createElement("div"); ).try_into().unwrap() } fn h1() -> Element { js!( return document.createElement("h1"); ).try_into().unwrap() } #[test] fn test_closest_finds_ancestor() { let parent = div(); let child = h1(); parent.append_child(&child); assert_eq!(child.closest("div").unwrap().unwrap().as_ref(), parent.as_ref()); } #[test] fn test_closest_not_found() { let parent = div(); let child = h1(); parent.append_child(&child); assert!(child.closest("p").unwrap().is_none()); } #[test] fn test_closest_syntax_error() { let parent = div(); let child = div(); parent.append_child(&child); assert!(child.closest("invalid syntax +#8$()@!(#").is_err()); } #[test] fn insert_adjacent_html() { let root = document().create_element("div").unwrap(); let child = document().create_element("span").unwrap(); child.set_text_content("child"); root.append_child(&child); child.insert_html_before(" foo ").unwrap(); child.prepend_html("afterbegin").unwrap(); child.append_html("

Before end

").unwrap(); child.insert_html_after("after end ").unwrap(); let html = js!(return @{root}.innerHTML); assert_eq!(html, " foo afterbeginchild

Before end

after end "); } #[test] fn insert_adjacent_html_empty() { let root = document().create_element("div").unwrap(); root.append_html("").unwrap(); let html = js!(return @{root}.innerHTML); assert_eq!(html, ""); } #[test] fn insert_adjacent_html_not_modifiable() { let doc = document().document_element().unwrap(); assert!(match doc.insert_html_before("foobar").unwrap_err() { InsertAdjacentError::NoModificationAllowedError(_) => true, _ => false, }); } #[test] fn test_attach_shadow_mode_open() { let element = document().create_element("div").unwrap(); let shadow_root = element.attach_shadow(ShadowRootMode::Open).unwrap(); assert_eq!(shadow_root.mode(), ShadowRootMode::Open); assert_eq!(element.shadow_root(), Some(shadow_root)); } #[test] fn test_attach_shadow_mode_closed() { let element = document().create_element("div").unwrap(); let shadow_root = element.attach_shadow(ShadowRootMode::Closed).unwrap(); assert_eq!(shadow_root.mode(), ShadowRootMode::Closed); assert!(element.shadow_root().is_none()); } } stdweb-0.4.20/src/webapi/error.rs010064400017500001750000000061261351311462600150520ustar0000000000000000use webcore::value::Reference; use webcore::try_from::TryInto; use webcore::reference_type::ReferenceType; /// Represents the JavaScript `Error` interface. An `Error` is thrown whenever a run-time error /// occurs. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error) // https://www.ecma-international.org/ecma-262/6.0/#sec-error-objects pub trait IError: ReferenceType { /// Returns a human-readable description of the error. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/message) // https://www.ecma-international.org/ecma-262/6.0/#sec-error.prototype.message #[inline] fn message( &self ) -> String { js!( return @{self.as_ref()}.message; ).try_into().unwrap() } /// Returns a name specifiying the type of error. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/name) // https://www.ecma-international.org/ecma-262/6.0/#sec-error.prototype.name #[inline] fn name( &self ) -> String { js!( return @{self.as_ref()}.name; ).try_into().unwrap() } } /// A reference to a JavaScript `Error` object. An `Error` is thrown whenever a run-time error /// occurs. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error) // https://www.ecma-international.org/ecma-262/6.0/#sec-error-objects #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "Error")] pub struct Error( Reference ); impl Error { /// Creates a new `Error` with the specified `description`. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error) #[inline] pub fn new( description: &str ) -> Self { js!( return new Error( @{description} ); ).try_into().unwrap() } } impl IError for Error {} error_boilerplate! { Error } /// Used to indicate an unsuccessful operation when none of the other NativeError objects are an appropriate indication of the failure cause. // https://tc39.github.io/ecma262/#sec-native-error-types-used-in-this-standard-typeerror #[derive(Clone, Debug, ReferenceType)] #[reference(subclass_of(Error))] #[reference(instance_of = "TypeError")] pub struct TypeError( Reference ); impl IError for TypeError {} error_boilerplate! { TypeError } #[cfg(test)] mod test { use super::*; #[test] fn test_error() { use std::fmt::Write; let error: Error = js!( return new Error("foo"); ).try_into().unwrap(); assert_eq!(error.name(), "Error"); assert_eq!(error.message(), "foo"); let mut text = String::new(); write!(&mut text, "{}", error).unwrap(); assert_eq!(&text, "Error: foo"); assert_eq!(std::error::Error::description(&error), "Error"); } #[test] fn test_type_error() { let _: TypeError = js!( return new TypeError( "Big bad wolf" ); ).try_into().unwrap(); } } stdweb-0.4.20/src/webapi/event.rs010064400017500001750000000274611354667070600150630ustar0000000000000000use webcore::value::Reference; use webcore::try_from::TryInto; use webcore::reference_type::ReferenceType; use webapi::event_target::EventTarget; use webapi::window::Window; /// The `IEvent` interface represents any event which takes place in the DOM; some /// are user-generated (such as mouse or keyboard events), while others are /// generated by APIs (such as events that indicate an animation has finished /// running, a video has been paused, and so forth). There are many types of event, /// some of which use other interfaces based on the main `IEvent` interface. `IEvent` /// itself contains the properties and methods which are common to all events. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Event) // https://dom.spec.whatwg.org/#event pub trait IEvent: ReferenceType { /// Indicates whether this event bubbles upward through the DOM. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Event) // https://dom.spec.whatwg.org/#ref-for-dom-event-bubbles%E2%91%A0 #[inline] fn bubbles( &self ) -> bool { js!( return @{self.as_ref()}.bubbles; ).try_into().unwrap() } /// A historical alias to `Event.stopPropagation()`. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Event/cancelBubble) // https://dom.spec.whatwg.org/#ref-for-dom-event-cancelbubble #[inline] fn cancel_bubble( &self ) -> bool { js!( return @{self.as_ref()}.cancelBubble; ).try_into().unwrap() } /// A historical alias to `Event.stopPropagation()`. /// Setting this to `true` before returning from an event handler will stop propagation /// of the event. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Event/cancelBubble) // https://dom.spec.whatwg.org/#ref-for-dom-event-cancelbubble #[inline] fn set_cancel_bubble( &self, value: bool ) { js! { @(no_return) @{self.as_ref()}.cancelBubble = @{value}; } } /// Indicates whether the event is cancelable. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Event/cancelable) // https://dom.spec.whatwg.org/#ref-for-dom-event-cancelable #[inline] fn cancelable( &self ) -> bool { js!( return @{self.as_ref()}.cancelable; ).try_into().unwrap() } /// A reference to the currently registered target of this event. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Event/currentTarget) // https://dom.spec.whatwg.org/#ref-for-dom-event-currenttarget%E2%91%A0 #[inline] fn current_target( &self ) -> Option< EventTarget > { js!( return @{self.as_ref()}.currentTarget; ).try_into().ok() } /// Indicates whether `preventDefault` has been called on this event. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Event/defaultPrevented) // https://dom.spec.whatwg.org/#ref-for-dom-event-defaultprevented #[inline] fn default_prevented( &self ) -> bool { js!( return @{self.as_ref()}.defaultPrevented; ).try_into().unwrap() } /// Indicates which phase of event flow is currently being evaluated. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Event/eventPhase) // https://dom.spec.whatwg.org/#ref-for-dom-event-eventphase%E2%91%A1 fn event_phase( &self ) -> EventPhase { match js!( return @{self.as_ref()}.eventPhase; ).try_into().unwrap() { 0 => EventPhase::None, 1 => EventPhase::Capturing, 2 => EventPhase::AtTarget, 3 => EventPhase::Bubbling, _ => unreachable!("Unexpected EventPhase type"), } } /// Prevents any further listeners from being called for this event. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Event/stopImmediatePropagation) #[inline] fn stop_immediate_propagation( &self ) { js! { @(no_return) @{self.as_ref()}.stopImmediatePropagation(); } } /// Stops the propagation of this event to descendants in the DOM. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Event/stopPropagation) // https://dom.spec.whatwg.org/#ref-for-dom-event-stopimmediatepropagation #[inline] fn stop_propagation( &self ) { js! { @(no_return) @{self.as_ref()}.stopPropagation(); } } /// Returns a reference to the target to which this event was originally registered. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Event/target) // https://dom.spec.whatwg.org/#ref-for-dom-event-target%E2%91%A1 #[inline] fn target( &self ) -> Option< EventTarget > { js!( return @{self.as_ref()}.target; ).try_into().ok() } /// Returns the time in milliseconds at which this event was created. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Event/timeStamp) // https://dom.spec.whatwg.org/#ref-for-dom-event-timestamp #[inline] fn time_stamp( &self ) -> Option< f64 > { js!( return @{self.as_ref()}.timeStamp; ).try_into().ok() } /// Indicates whether the event was generated by a user action. // https://dom.spec.whatwg.org/#ref-for-dom-event-istrusted #[inline] fn is_trusted( &self ) -> bool { js!( return @{self.as_ref()}.isTrusted; ).try_into().unwrap() } /// Returns a string containing the type of event. It is set when /// the event is constructed and is the name commonly used to refer /// to the specific event. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Event/type) // https://dom.spec.whatwg.org/#ref-for-dom-event-type%E2%91%A1 #[inline] fn event_type( &self ) -> String { js!( return @{self.as_ref()}.type; ).try_into().unwrap() } /// Cancels the event if it is cancelable, without /// stopping further propagation of the event. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault) // https://dom.spec.whatwg.org/#ref-for-dom-event-preventdefault%E2%91%A0 #[inline] fn prevent_default( &self ) { js! { @(no_return) @{self.as_ref()}.preventDefault(); } } } /// Indicates the phase of event flow during event proessing. // https://dom.spec.whatwg.org/#dom-event-eventphase #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum EventPhase { /// No event is currently being processed. None, /// The event is being propagated down through the target's ancestors. Capturing, /// The target is currently processing the event. AtTarget, /// The event is propagating back up through the target's ancestors. Bubbling, } /// A trait representing a concrete event type. pub trait ConcreteEvent: IEvent { /// A string representing the event type. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Event/type) const EVENT_TYPE: &'static str; } /// A reference to a JavaScript object which implements the [IEvent](trait.IEvent.html) /// interface. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Event) // https://dom.spec.whatwg.org/#event #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "Event")] pub struct Event( Reference ); impl IEvent for Event {} /// The `BeforeUnload` event fires when the window is about to be unloaded (to close the page or /// follow a link). If the event propagation is cancelled, the browser will present the user with /// a confirmation dialog allowing them to stay on the page or continue. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event) // https://html.spec.whatwg.org/multipage/indices.html#event-beforeunload #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "BeforeUnloadEvent")] #[reference(event = "beforeunload")] pub struct BeforeUnloadEvent( Reference ); impl IEvent for BeforeUnloadEvent {} /// The `Unload` event fires when the window has been unloaded and is no longer visible. This event /// can't be cancelled. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Window/unload_event) // https://html.spec.whatwg.org/multipage/indices.html#event-unload #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "UnloadEvent")] #[reference(event = "unload")] pub struct UnloadEvent( Reference ); impl IEvent for UnloadEvent {} /// The 'FullscreenChange' event fires when an element enters or exits fullscreen /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Document/fullscreenchange_event) // https://fullscreen.spec.whatwg.org/#handler-document-onfullscreenchange #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "Event")] #[reference(event = "fullscreenchange")] pub struct FullscreenChangeEvent( Reference ); impl IEvent for FullscreenChangeEvent {} /// The `IUiEvent` interface represents simple user interface events. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/UIEvent) // https://w3c.github.io/uievents/#uievent pub trait IUiEvent: IEvent { /// Provides the current click count for this event, if applicable. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/UIEvent/detail) // https://w3c.github.io/uievents/#dom-uievent-detail #[inline] fn detail( &self ) -> i32 { js!( return @{self.as_ref()}.detail; ).try_into().unwrap() } /// Returns the `WindowProxy` that generated the event. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/UIEvent/view) // https://w3c.github.io/uievents/#dom-uievent-view #[inline] fn view( &self ) -> Option< Window > { js!( return @{self.as_ref()}.view; ).try_into().ok() } } /// A reference to a JavaScript object which implements the [IUiEvent](trait.IUiEvent.html) /// interface. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/UIEvent) // https://w3c.github.io/uievents/#uievent #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "UIEvent")] #[reference(subclass_of(Event))] pub struct UiEvent( Reference ); impl IEvent for UiEvent {} impl IUiEvent for UiEvent {} #[cfg(all(test, feature = "web_test"))] mod tests { use super::*; #[test] fn test_event() { let event: Event = js!( return new Event("dummy") ).try_into().unwrap(); assert_eq!( event.event_type(), "dummy" ); assert_eq!( event.bubbles(), false ); assert!( !event.cancel_bubble() ); assert!( !event.cancelable(), false ); assert!( event.current_target().is_none() ); assert!( !event.default_prevented() ); assert_eq!( event.event_phase(), EventPhase::None ); assert!( event.target().is_none() ); assert!( event.time_stamp().is_some() ); assert!( !event.is_trusted() ); event.stop_immediate_propagation(); event.stop_propagation(); } #[test] fn test_ui_event() { use webapi::events::mouse::ClickEvent; let event: UiEvent = js!( return new UIEvent( @{ClickEvent::EVENT_TYPE}, { detail: 1, } ) ).try_into().unwrap(); assert_eq!( event.event_type(), ClickEvent::EVENT_TYPE ); assert_eq!( event.detail(), 1 ); assert!( event.view().is_none() ); } } stdweb-0.4.20/src/webapi/event_target.rs010064400017500001750000000063351337463116100164150ustar0000000000000000use std::fmt; use webcore::value::Reference; use webcore::try_from::TryInto; use webcore::reference_type::ReferenceType; use webcore::mutfn::Mut; use webapi::event::{ConcreteEvent, IEvent}; use private::TODO; /// A handle to a particular event listener. pub struct EventListenerHandle { event_type: &'static str, reference: Reference, listener_reference: Reference } impl fmt::Debug for EventListenerHandle { fn fmt( &self, formatter: &mut fmt::Formatter ) -> fmt::Result { write!( formatter, "EventListenerHandle {{ event_type: {}, reference: {:?} }}", self.event_type, self.reference ) } } impl EventListenerHandle { /// Removes the listener from the [IEventTarget](trait.IEventTarget.html) on /// which it was previously registered. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/removeEventListener) // https://dom.spec.whatwg.org/#ref-for-dom-eventtarget-removeeventlistener%E2%91%A0 pub fn remove( self ) { js! { @(no_return) var listener = @{&self.listener_reference}; @{&self.reference}.removeEventListener( @{self.event_type}, listener ); listener.drop(); } } } /// `IEventTarget` is an interface implemented by objects that /// can receive events and may have listeners for them. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget) // https://dom.spec.whatwg.org/#eventtarget pub trait IEventTarget: ReferenceType { /// Adds given event handler to the list of event listeners for /// the specified `EventTarget` on which it's called. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener) // https://dom.spec.whatwg.org/#ref-for-dom-eventtarget-addeventlistener%E2%91%A0 fn add_event_listener< T, F >( &self, listener: F ) -> EventListenerHandle where T: ConcreteEvent, F: FnMut( T ) + 'static { let reference = self.as_ref(); let listener_reference = js! { var listener = @{Mut(listener)}; @{reference}.addEventListener( @{T::EVENT_TYPE}, listener ); return listener; }.try_into().unwrap(); EventListenerHandle { event_type: T::EVENT_TYPE, reference: reference.clone(), listener_reference: listener_reference } } /// Dispatches an `Event` at this `EventTarget`, invoking the affected event listeners in the /// appropriate order. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/dispatchEvent) fn dispatch_event< T: IEvent >( &self, event: &T ) -> Result< bool, TODO > { Ok( js! ( return @{self.as_ref()}.dispatchEvent( @{event.as_ref()} ); ).try_into().unwrap() ) } } /// A reference to a JavaScript object which implements the [IEventTarget](trait.IEventTarget.html) /// interface. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget) // https://dom.spec.whatwg.org/#eventtarget #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "EventTarget")] pub struct EventTarget( Reference ); impl IEventTarget for EventTarget {} stdweb-0.4.20/src/webapi/events/dom.rs010064400017500001750000000171431337463116100160100ustar0000000000000000use webcore::value::Reference; use webapi::event::{IEvent, IUiEvent, UiEvent, Event}; /// The `ChangeEvent` is fired for input, select, and textarea /// elements when a change to the element's value is committed /// by the user. Unlike the input event, the change event is not /// necessarily fired for each change to an element's value. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/change) // https://html.spec.whatwg.org/#event-change #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "Event")] #[reference(event = "change")] #[reference(subclass_of(Event))] pub struct ChangeEvent( Reference ); impl IEvent for ChangeEvent {} /// The `InputEvent` is fired synchronously when the value of an /// input, select, or textarea element is changed. For input elements /// with type=checkbox or type=radio, the input event should fire when /// a user toggles the control (via touch, mouse or keyboard) per the /// HTML5 specification, but historically, this has not been the case. /// Check compatibility, or attach to the change event instead for /// elements of these types. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/input) // https://html.spec.whatwg.org/#event-input #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "Event")] #[reference(event = "input")] #[reference(subclass_of(Event))] pub struct InputEvent( Reference ); impl IEvent for InputEvent {} /// The `ResourceLoadEvent` is fired when a resource and its dependent resources have finished loading. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/load) // https://w3c.github.io/uievents/#load #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "UIEvent")] #[reference(event = "load")] #[reference(subclass_of(Event, UiEvent))] pub struct ResourceLoadEvent( Reference ); impl IEvent for ResourceLoadEvent {} impl IUiEvent for ResourceLoadEvent {} /// The `ResourceAbortEvent` is fired when the loading of a resource has been aborted. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/abort) // https://w3c.github.io/uievents/#event-type-abort #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "UIEvent")] #[reference(event = "abort")] #[reference(subclass_of(Event, UiEvent))] pub struct ResourceAbortEvent( Reference ); impl IEvent for ResourceAbortEvent {} impl IUiEvent for ResourceAbortEvent {} /// The `ResourceErrorEvent` is fired when an error occurred; the exact circumstances vary, /// since this event is used from a variety of APIs. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/error) // https://w3c.github.io/uievents/#event-type-error #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "UIEvent")] #[reference(event = "error")] #[reference(subclass_of(Event, UiEvent))] pub struct ResourceErrorEvent( Reference ); impl IEvent for ResourceErrorEvent {} impl IUiEvent for ResourceErrorEvent {} /// The resize event is fired when the document view has been resized. /// /// MDN incorrectly documents this as a UIEvent, but in browsers it is actually /// just an Event. /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/resize) // https://drafts.csswg.org/cssom-view/#eventdef-window-resize #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "Event")] #[reference(event = "resize")] #[reference(subclass_of(Event))] pub struct ResizeEvent( Reference ); impl IEvent for ResizeEvent {} /// The scroll event is fired when the document view or an element has been scrolled. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/scroll) // https://drafts.csswg.org/cssom-view/#eventdef-document-scroll #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "Event")] #[reference(event = "scroll")] #[reference(subclass_of(Event))] pub struct ScrollEvent( Reference ); impl IEvent for ScrollEvent {} /// The readystatechange event is fired when the readyState attribute of a document has changed. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/readystatechange) // https://html.spec.whatwg.org/#event-readystatechange #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "Event")] #[reference(event = "readystatechange")] #[reference(subclass_of(Event))] pub struct ReadyStateChangeEvent( Reference ); impl IEvent for ReadyStateChangeEvent {} /// The submit event is fired when a form is submitted. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/submit) // https://html.spec.whatwg.org/#event-submit #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "Event")] #[reference(event = "submit")] #[reference(subclass_of(Event))] pub struct SubmitEvent( Reference ); impl IEvent for SubmitEvent {} /// The selectionchange event of the Selection API is fired when the current text selection on a /// document is changed. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/selectionchange) // https://w3c.github.io/selection-api/#selectionchange-event #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "Event")] #[reference(event = "selectionchange")] #[reference(subclass_of(Event))] pub struct SelectionChangeEvent( Reference ); impl IEvent for SelectionChangeEvent {} #[cfg(all(test, feature = "web_test"))] mod tests { use super::*; use webcore::try_from::TryInto; use webapi::event::ConcreteEvent; #[test] fn test_change_event() { let event: ChangeEvent = js!( return new Event( @{ChangeEvent::EVENT_TYPE} ); ).try_into().unwrap(); assert_eq!( event.event_type(), ChangeEvent::EVENT_TYPE ); } #[test] fn test_input_event() { let event: InputEvent = js!( return new Event( @{InputEvent::EVENT_TYPE} ); ).try_into().unwrap(); assert_eq!( event.event_type(), InputEvent::EVENT_TYPE ); } #[test] fn test_resource_load_event() { let event: ResourceLoadEvent = js!( return new UIEvent( @{ResourceLoadEvent::EVENT_TYPE} ); ).try_into().unwrap(); assert_eq!( event.event_type(), ResourceLoadEvent::EVENT_TYPE ); } #[test] fn test_resource_abort_event() { let event: ResourceAbortEvent = js!( return new UIEvent( @{ResourceAbortEvent::EVENT_TYPE} ); ).try_into().unwrap(); assert_eq!( event.event_type(), ResourceAbortEvent::EVENT_TYPE ); } #[test] fn test_scroll_event() { let event: ScrollEvent = js!( return new Event( @{ScrollEvent::EVENT_TYPE} ); ).try_into().unwrap(); assert_eq!( event.event_type(), ScrollEvent::EVENT_TYPE ); } #[test] fn test_ready_state_change_event() { let event: ReadyStateChangeEvent = js!( return new Event( @{ReadyStateChangeEvent::EVENT_TYPE} ); ).try_into().unwrap(); assert_eq!( event.event_type(), ReadyStateChangeEvent::EVENT_TYPE); } #[test] fn test_submit_event() { let event: SubmitEvent = js!( return new Event( @{SubmitEvent::EVENT_TYPE} ); ).try_into().unwrap(); assert_eq!( event.event_type(), SubmitEvent::EVENT_TYPE); } #[test] fn test_selectionchange_event() { let event: SelectionChangeEvent = js!( return new Event( @{SelectionChangeEvent::EVENT_TYPE} ); ).try_into().unwrap(); assert_eq!( event.event_type(), SelectionChangeEvent::EVENT_TYPE); } } stdweb-0.4.20/src/webapi/events/drag.rs010064400017500001750000000703041337463116100161440ustar0000000000000000#[cfg(feature = "futures-support")] use futures_channel::oneshot; use webapi::event::{IEvent, IUiEvent, UiEvent, Event}; use webapi::events::mouse::{IMouseEvent, MouseEvent}; use webapi::file::File; use webcore::once::Once; use webcore::value::{Reference, Value}; use webcore::try_from::TryInto; use webapi::file_list::FileList; use webapi::html_elements::ImageElement; use webapi::dom_exception::NotSupportedError; use webapi::dom_exception::InvalidStateError; /// The DragEvent interface is a DOM event that represents a drag and drop interaction. /// The user initiates a drag by placing a pointer device (such as a mouse) on the touch surface /// and then dragging the pointer to a new location (such as another DOM element). /// /// This interface inherits properties from MouseEvent and Event. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DragEvent) // https://www.w3.org/TR/html51/editing.html#dragevent-dragevent pub trait IDragEvent: IMouseEvent { /// The DataEvent.dataTransfer property holds the drag operation's data (as a DataTransfer object). /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DragEvent/dataTransfer) // https://www.w3.org/TR/html51/editing.html#ref-for-dom-dragevent-datatransfer-1 #[inline] fn data_transfer(&self) -> Option { js!( return @{self.as_ref()}.dataTransfer; ).try_into().unwrap() } } /// A reference to a JavaScript object which implements the [IDragEvent](trait.IDragEvent.html) /// interface. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DragEvent) // https://www.w3.org/TR/html51/editing.html#the-dragevent-interface #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "DragEvent")] #[reference(subclass_of(Event, UiEvent, MouseEvent))] pub struct DragRelatedEvent(Reference); impl IEvent for DragRelatedEvent {} impl IUiEvent for DragRelatedEvent {} impl IMouseEvent for DragRelatedEvent {} impl IDragEvent for DragRelatedEvent {} /// The drag event is fired every few hundred milliseconds as an element or text selection is being /// dragged by the user. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/drag) // https://www.w3.org/TR/html51/editing.html#eventdef-global-drag #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "DragEvent")] #[reference(event = "drag")] #[reference(subclass_of(Event, UiEvent, MouseEvent, DragRelatedEvent))] pub struct DragEvent(Reference); impl IEvent for DragEvent {} impl IUiEvent for DragEvent {} impl IMouseEvent for DragEvent {} impl IDragEvent for DragEvent {} /// The dragstart event is fired when the user starts dragging an element or text selection. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/dragstart) // https://www.w3.org/TR/html51/editing.html#eventdef-global-dragstart #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "DragEvent")] #[reference(event = "dragstart")] #[reference(subclass_of(Event, UiEvent, MouseEvent, DragRelatedEvent))] pub struct DragStartEvent(Reference); impl IEvent for DragStartEvent {} impl IUiEvent for DragStartEvent {} impl IMouseEvent for DragStartEvent {} impl IDragEvent for DragStartEvent {} /// The dragenter event is fired when a dragged element or text selection enters a valid drop target. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/dragenter) // https://www.w3.org/TR/html51/editing.html#eventdef-global-dragenter #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "DragEvent")] #[reference(event = "dragenter")] #[reference(subclass_of(Event, UiEvent, MouseEvent, DragRelatedEvent))] pub struct DragEnterEvent(Reference); impl IEvent for DragEnterEvent {} impl IUiEvent for DragEnterEvent {} impl IMouseEvent for DragEnterEvent {} impl IDragEvent for DragEnterEvent {} /// The dragexit event is fired when an element is no longer the drag operation's immediate /// selection target. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/dragexit) // https://www.w3.org/TR/html51/editing.html#eventdef-global-dragexit #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "DragEvent")] #[reference(event = "dragexit")] #[reference(subclass_of(Event, UiEvent, MouseEvent, DragRelatedEvent))] pub struct DragExitEvent(Reference); impl IEvent for DragExitEvent {} impl IUiEvent for DragExitEvent {} impl IMouseEvent for DragExitEvent {} impl IDragEvent for DragExitEvent {} /// The dragleave event is fired when a dragged element or text selection leaves a valid drop target. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/dragleave) // https://www.w3.org/TR/html51/editing.html#eventdef-global-dragleave #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "DragEvent")] #[reference(event = "dragleave")] #[reference(subclass_of(Event, UiEvent, MouseEvent, DragRelatedEvent))] pub struct DragLeaveEvent(Reference); impl IEvent for DragLeaveEvent {} impl IUiEvent for DragLeaveEvent {} impl IMouseEvent for DragLeaveEvent {} impl IDragEvent for DragLeaveEvent {} /// The dragover event is fired when an element or text selection is being dragged over a valid drop /// target (every few hundred milliseconds). /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/dragover) // https://www.w3.org/TR/html51/editing.html#eventdef-global-dragover #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "DragEvent")] #[reference(event = "dragover")] #[reference(subclass_of(Event, UiEvent, MouseEvent, DragRelatedEvent))] pub struct DragOverEvent(Reference); impl IEvent for DragOverEvent {} impl IUiEvent for DragOverEvent {} impl IMouseEvent for DragOverEvent {} impl IDragEvent for DragOverEvent {} /// The drop event is fired when an element or text selection is dropped on a valid drop target. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/drop) // https://www.w3.org/TR/html51/editing.html#eventdef-global-drop #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "DragEvent")] #[reference(event = "drop")] #[reference(subclass_of(Event, UiEvent, MouseEvent, DragRelatedEvent))] pub struct DragDropEvent(Reference); impl IEvent for DragDropEvent {} impl IUiEvent for DragDropEvent {} impl IMouseEvent for DragDropEvent {} impl IDragEvent for DragDropEvent {} /// The dragend event is fired when a drag operation is being ended (by releasing a mouse button or /// hitting the escape key). /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/dragend) // https://www.w3.org/TR/html51/editing.html#eventdef-global-dragend #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "DragEvent")] #[reference(event = "dragend")] #[reference(subclass_of(Event, UiEvent, MouseEvent, DragRelatedEvent))] pub struct DragEndEvent(Reference); impl IEvent for DragEndEvent {} impl IUiEvent for DragEndEvent {} impl IMouseEvent for DragEndEvent {} impl IDragEvent for DragEndEvent {} /// The DataTransfer object is used to hold the data that is being dragged during a drag and drop /// operation. /// /// It may hold one or more data items, each of one or more data types. /// For more information about drag and drop, see HTML Drag and Drop API. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer) // https://www.w3.org/TR/html51/editing.html#datatransfer-datatransfer #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "DataTransfer")] pub struct DataTransfer( Reference ); impl DataTransfer { /// Gets the type of drag-and-drop operation currently selected type. /// The value must be none, copy, link or move. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/dropEffect) // https://www.w3.org/TR/html51/editing.html#ref-for-dom-datatransfer-dropeffect-2 pub fn drop_effect( &self ) -> DropEffect { let v: String = js!( return @{self.as_ref()}.dropEffect; ).try_into().unwrap(); match v.as_ref() { "copy" => DropEffect::Copy, "move" => DropEffect::Move, "link" => DropEffect::Link, "none" => DropEffect::None, other => panic!("Expected valid dropEffect value, got {:?}", other), } } /// Sets the type of drag-and-drop operation currently selected. /// The value must be none, copy, link or move. /// /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/dropEffect) // https://www.w3.org/TR/html51/editing.html#ref-for-dom-datatransfer-dropeffect-2 pub fn set_drop_effect( &self, value: DropEffect ) { js! { @(no_return) @{self.as_ref()}.dropEffect = @{match value { DropEffect::Copy => "copy", DropEffect::Move => "move", DropEffect::Link => "link", DropEffect::None => "none", }}; } } /// Provides all of the types of operations that are possible. /// Must be one of none, copy, copyLink, copyMove, link, linkMove, move, all or uninitialized. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/effectAllowed) // https://www.w3.org/TR/html51/editing.html#ref-for-dom-datatransfer-effectallowed-1 pub fn effect_allowed( &self ) -> EffectAllowed { let v: String = js!( return @{self.as_ref()}.effectAllowed; ).try_into().unwrap(); match v.as_ref() { "none" => EffectAllowed::None, "copy" => EffectAllowed::Copy, "copyLink" => EffectAllowed::CopyLink, "copyMove" => EffectAllowed::CopyMove, "link" => EffectAllowed::Link, "linkMove" => EffectAllowed::LinkMove, "move" => EffectAllowed::Move, "all" => EffectAllowed::All, "uninitialized" => EffectAllowed::Uninitialized, other => panic!("Expected valid effectAllowed value, got {:?}", other), } } /// Sets the effect that is allowed for a drag operation. /// Must be one of none, copy, copyLink, copyMove, link, linkMove, move, all or uninitialized. /// /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/effectAllowed) // https://www.w3.org/TR/html51/editing.html#ref-for-dom-datatransfer-effectallowed-1 pub fn set_effect_allowed( &self, value: EffectAllowed ) { js! { @(no_return) @{self.as_ref()}.effectAllowed = @{match value { EffectAllowed::None => "none", EffectAllowed::Copy => "copy", EffectAllowed::CopyLink => "copyLink", EffectAllowed::CopyMove => "copyMove", EffectAllowed::Link => "link", EffectAllowed::LinkMove => "linkMove", EffectAllowed::Move => "move", EffectAllowed::All => "all", EffectAllowed::Uninitialized => "uninitialized", }}; } } /// Gives a DataTransferItemList object which is a list of all of the drag data. /// /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/items) // https://www.w3.org/TR/html51/editing.html#ref-for-dom-datatransfer-items-1 pub fn items( &self ) -> DataTransferItemList { js!( return @{self.as_ref()}.items; ).try_into().unwrap() } /// Contains a list of all the local files available on the data transfer. /// If the drag operation doesn't involve dragging files, this property is an empty list. /// /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/files) // https://www.w3.org/TR/html51/editing.html#ref-for-dom-datatransfer-files-1 pub fn files( &self ) -> FileList { js!( return @{self.as_ref()}.files; ).try_into().unwrap() } /// An array of strings giving the formats that were set in the dragstart event. /// /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/types) // https://www.w3.org/TR/html51/editing.html#ref-for-dom-datatransfer-types-1 pub fn types( &self ) -> Vec { js!( return @{self.as_ref()}.types; ).try_into().unwrap() } /// Remove the data associated with a given type. The type argument is optional. /// If the type is empty or not specified, the data associated with all types is removed. /// If data for the specified type does not exist, or the data transfer contains no data, /// this method will have no effect. /// /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/clearData) // https://www.w3.org/TR/html51/editing.html#ref-for-dom-datatransfer-cleardata-1 pub fn clear_data( &self, format: Option<&str> ) { match format { None => js!(@(no_return) @{self.as_ref()}.clearData()), Some(x) => js!(@(no_return) @{self.as_ref()}.clearData(@{x})) }; } /// Retrieves the data for a given type, or an empty string if data for that type does not exist /// or the data transfer contains no data. /// /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/getData) // https://www.w3.org/TR/html51/editing.html#ref-for-dom-datatransfer-getdata-1 pub fn get_data( &self, format: &str ) -> String { js!( return @{self.as_ref()}.getData(@{format}); ).try_into().unwrap() } /// Set the data for a given type. /// If data for the type does not exist, it is added at the end, such that the last item in the /// types list will be the new format. /// If data for the type already exists, the existing data is replaced in the same position. /// /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/setData) // https://www.w3.org/TR/html51/editing.html#ref-for-dom-datatransfer-setdata-1 pub fn set_data( &self, format: &str, data: &str ) { js!(@(no_return) @{self.as_ref()}.setData(@{format}, @{data}); ); } /// Set the image to be used for dragging if a custom one is desired. /// /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/setDragImage) // https://www.w3.org/TR/html51/editing.html#ref-for-dom-datatransfer-setdragimage-1 pub fn set_drag_image( &self, img: &ImageElement, x_offset: i32, y_offset: i32 ) { js!(@(no_return) @{self.as_ref()}.setDragImage(@{img.as_ref()}, @{x_offset}, @{y_offset}); ); } } /// A DOMString representing the drag operation effect. // https://www.w3.org/TR/html51/editing.html#dom-datatransfer-dropeffect #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum DropEffect { /// A copy of the source item is made at the new location Copy, /// An item is moved to a new location. Move, /// A link is established to the source at the new location. Link, /// The item may not be dropped. None, } /// A DOMString representing the drag operation that is allowed. // https://www.w3.org/TR/html51/editing.html#dom-datatransfer-effectallowed #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum EffectAllowed { /// The item may not be dropped. None, /// A copy of the source item may be made at the new location. Copy, /// A copy or link operation is permitted. CopyLink, /// A copy or move operation is permitted. CopyMove, /// A link may be established to the source at the new location. Link, /// A link or move operation is permitted. LinkMove, /// An item may be moved to a new location. Move, /// All operations are permitted. All, /// The default value when the effect has not been set, equivalent to all. Uninitialized, } /// The DataTransferItemList object is a list of DataTransferItem objects representing items being /// dragged. /// During a drag operation, each DragEvent has a dataTransfer property and that property is a /// DataTransferItemList. /// /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItemList) // https://www.w3.org/TR/html51/editing.html#datatransferitemlist-datatransferitemlist #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "DataTransferItemList")] pub struct DataTransferItemList( Reference ); impl DataTransferItemList { /// An unsigned long that is the number of drag items in the list. /// /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItemList/length) // https://www.w3.org/TR/html51/editing.html#ref-for-dom-datatransferitemlist-length-1 pub fn len( &self ) -> u32 { js!( return @{self.as_ref()}.length; ).try_into().unwrap() } /// Adds an item of kind "string" to the drag item list and returns /// a DataTransferItem object for the new item. /// /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItemList/add) // https://www.w3.org/TR/html51/editing.html#ref-for-dom-datatransferitemlist-add-1 pub fn add_string( &self, data: &str, ty: &str ) -> Result, NotSupportedError> { js_try!( return @{self.as_ref()}.add(@{data}, @{ty}); ).unwrap() } /// Adds an item of kind "file" to the drag item list and returns /// a DataTransferItem object for the new item. /// /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItemList/add) // https://www.w3.org/TR/html51/editing.html#ref-for-dom-datatransferitemlist-add-2 pub fn add_file( &self, file: &File ) -> Option { js!( return @{self.as_ref()}.add(@{file}); ).try_into().unwrap() } /// Removes the drag item from the list at the given index. /// /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItemList/remove) // https://www.w3.org/TR/html51/editing.html#ref-for-dom-datatransferitemlist-remove-1 pub fn remove( &self, index: u32 ) -> Result<(), InvalidStateError> { js_try!(@{self.as_ref()}.remove(@{index})).unwrap() } /// Removes all of the drag items from the list. /// /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItemList/clear) // https://www.w3.org/TR/html51/editing.html#ref-for-dom-datatransferitemlist-clear-1 pub fn clear( &self ) { js!(@(no_return) @{self.as_ref()}.clear()); } /// Getter that returns a DataTransferItem at the given index. /// /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItemList/DataTransferItem) // https://www.w3.org/TR/html51/editing.html#ref-for-datatransferitem-datatransferitem-1 pub fn index( &self, index: u32 ) -> Option { let v: Value = js!( return @{self.as_ref()}[@{index}]; ); match v { Value::Reference(_) => Some(v.try_into().unwrap()), _ => None, } } /// Returns an iterator over the list pub fn iter( &self ) -> DataTransferItemIter { DataTransferItemIter { list: self.clone(), index: 0, } } } impl IntoIterator for DataTransferItemList { type Item = DataTransferItem; type IntoIter = DataTransferItemIter; #[inline] fn into_iter( self ) -> Self::IntoIter { DataTransferItemIter { list: self, index: 0 } } } impl< 'a > IntoIterator for &'a DataTransferItemList { type Item = DataTransferItem; type IntoIter = DataTransferItemIter; #[inline] fn into_iter( self ) -> Self::IntoIter { DataTransferItemIter { list: self.clone(), index: 0 } } } impl Iterator for DataTransferItemIter { type Item = DataTransferItem; fn next( &mut self ) -> Option< Self::Item > { let v = self.list.index(self.index); if v.is_some() { self.index += 1; } v } } #[derive(Debug)] pub struct DataTransferItemIter { list: DataTransferItemList, index: u32, } /// The DataTransferItem object represents one drag data item. During a drag operation, each drag /// event has a dataTransfer property which contains a list of drag data items. Each item in the /// list is a DataTransferItem object. /// /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItem) // https://www.w3.org/TR/html51/editing.html#datatransferitem-datatransferitem #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "DataTransferItem")] pub struct DataTransferItem( Reference ); impl DataTransferItem { /// The kind of drag data item, string or file. /// /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItem/kind) // https://www.w3.org/TR/html51/editing.html#ref-for-dom-datatransferitem-kind-13 pub fn kind( &self ) -> DataTransferItemKind { let kind: String = js!( return @{self.as_ref()}.kind; ).try_into().unwrap(); match kind.as_ref() { "string" => DataTransferItemKind::String, "file" => DataTransferItemKind::File, other => DataTransferItemKind::__Other(OtherKind { name: String::from(other) }), } } /// The drag data item's type, typically a MIME type. /// /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItem/type) // https://www.w3.org/TR/html51/editing.html#ref-for-dom-datatransferitem-type-2 pub fn ty( &self ) -> String { js!( return @{self.as_ref()}.type; ).try_into().unwrap() } /// Returns the File object associated with the drag data item /// (or null if the drag item is not a file) /// /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItem/getAsFile) // https://www.w3.org/TR/html51/editing.html#ref-for-dom-datatransferitem-getasfile-1 pub fn get_as_file( &self ) -> Option { js!( return @{self.as_ref()}.getAsFile(); ).try_into().unwrap() } /// Invokes the specified callback with the drag data item string as its argument. /// /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItem/getAsString) // https://www.w3.org/TR/html51/editing.html#ref-for-dom-datatransferitem-getasstring-1 pub fn get_as_string( &self, callback: F ) where F: FnOnce(String) + 'static { js!(@(no_return) @{self.as_ref()}.getAsString(@{Once(callback)}); ); } /// Invokes the specified callback with the drag data item string as its argument. /// /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItem/getAsString) // https://www.w3.org/TR/html51/editing.html#ref-for-dom-datatransferitem-getasstring-1 #[cfg(feature = "futures-support")] pub fn get_as_string_future( &self ) -> oneshot::Receiver { let (sender, receiver) = oneshot::channel(); let callback = |s: String| { match sender.send(s) { Ok(_) => {}, Err(_) => {}, }; }; js!(@(no_return) @{self.as_ref()}.getAsString(@{Once(callback)}); ); receiver } } /// The kind of drag data item, string or file. /// /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItem/kind) // https://www.w3.org/TR/html51/editing.html#ref-for-dom-datatransferitem-kind-13 // TODO use #[non_exhaustive] when available #[derive(Clone, Debug, PartialEq, Eq)] pub enum DataTransferItemKind { /// If the drag data item is a file. File, /// If the kind of drag data item is a plain Unicode string. String, /// If the kind of drag data is something different (e.g. dragging an tag in Firefox) #[doc(hidden)] __Other(OtherKind), } impl DataTransferItemKind { /// Returns the string representation of this DataTransferItemKind /// Useful in case the browser returns a non-standard kind that you want to special case. pub fn as_str( &self ) -> &str { match *self { DataTransferItemKind::File => "file", DataTransferItemKind::String => "string", DataTransferItemKind::__Other( ref other_kind ) => &other_kind.name } } } #[derive(Clone, Debug, PartialEq, Eq)] pub struct OtherKind { name: String, } #[cfg(all(test, feature = "web_test"))] mod tests { use super::*; use webapi::event::ConcreteEvent; #[test] fn test_drag_event() { let event: DragRelatedEvent = js!( return new DragEvent( @{DragStartEvent::EVENT_TYPE}, { dataTransfer: new DataTransfer() } ); ).try_into().unwrap(); // effects assert_eq!(event.event_type(), DragStartEvent::EVENT_TYPE); assert_eq!(event.data_transfer().unwrap().effect_allowed(), EffectAllowed::None); assert_eq!(event.data_transfer().unwrap().drop_effect(), DropEffect::None); event.data_transfer().unwrap().set_effect_allowed(EffectAllowed::CopyMove); event.data_transfer().unwrap().set_drop_effect(DropEffect::Copy); // TODO how to test? can only set these during ondragstart event triggered in browser // assert_eq!(event.data_transfer().effect_allowed(), EffectAllowed::CopyMove); // assert_eq!(event.data_transfer().drop_effect(), DropEffect::Copy); // get, set, clear data event.data_transfer().unwrap().set_data("myformat", "mydata"); event.data_transfer().unwrap().set_data("myformat2", "mydata2"); event.data_transfer().unwrap().clear_data(Some("myformat3")); assert_eq!(event.data_transfer().unwrap().get_data("myformat"), String::from("mydata")); event.data_transfer().unwrap().clear_data(Some("myformat")); assert_eq!(event.data_transfer().unwrap().get_data("myformat"), String::from("")); assert_eq!(event.data_transfer().unwrap().get_data("myformat2"), String::from("mydata2")); event.data_transfer().unwrap().clear_data(None); assert_eq!(event.data_transfer().unwrap().get_data("myformat2"), String::from("")); let img = ImageElement::new(); event.data_transfer().unwrap().set_drag_image(&img, 10, 10); // types assert_eq!(event.data_transfer().unwrap().types().len(), 0); // items assert_eq!(event.data_transfer().unwrap().items().len(), 0); let data = "mydata"; let ty = "text/plain"; let item = event.data_transfer().unwrap().items().add_string(data, ty).unwrap().unwrap(); assert_eq!(item.ty(), ty); assert_eq!(item.kind(), DataTransferItemKind::String); // TODO(https://github.com/koute/stdweb/issues/128) fix when async unit testing is available // item.get_as_string().and_then(|s| { // assert_eq!(data, s); // assert_eq!(1, 1); // assert_eq!(2, 1); // }); let filename = "myname"; let file = js!(return new File(["content"], @{filename})).try_into().unwrap(); event.data_transfer().unwrap().items().add_file(&file).unwrap(); assert_eq!(event.data_transfer().unwrap().items().len(), 2); assert_eq!(event.data_transfer().unwrap().items().iter().count(), 2); assert!(event.data_transfer().unwrap().items().index(2).is_none()); assert_eq!(event.data_transfer().unwrap().files().len(), 1); let item = event.data_transfer().unwrap().items().index(1).unwrap(); assert_eq!(item.kind(), DataTransferItemKind::File); assert_eq!(item.get_as_file().unwrap().name(), filename); let result = event.data_transfer().unwrap().items().remove(0); assert!(result.is_ok()); assert_eq!(event.data_transfer().unwrap().items().len(), 1); event.data_transfer().unwrap().items().clear(); assert_eq!(event.data_transfer().unwrap().items().len(), 0); } } stdweb-0.4.20/src/webapi/events/focus.rs010064400017500001750000000057351337463116100163540ustar0000000000000000use webcore::value::Reference; use webcore::try_from::TryInto; use webapi::event_target::EventTarget; use webapi::event::{IEvent, Event}; /// The `IFocusEvent` interface represents focus-related /// events. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/FocusEvent) // https://w3c.github.io/uievents/#focusevent pub trait IFocusEvent: IEvent { /// Returns the secondary target of this event, if any. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/FocusEvent/relatedTarget) // https://w3c.github.io/uievents/#dom-focusevent-relatedtarget #[inline] fn related_target( &self ) -> Option< EventTarget > { js!( return @{self.as_ref()}.relatedTarget; ).try_into().ok() } } /// A reference to a JavaScript object which implements the [IFocusEvent](trait.IFocusEvent.html) /// interface. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/FocusEvent) // https://w3c.github.io/uievents/#focusevent #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "FocusEvent")] #[reference(subclass_of(Event))] pub struct FocusRelatedEvent( Reference ); impl IEvent for FocusRelatedEvent {} impl IFocusEvent for FocusRelatedEvent {} /// The `FocusEvent` is fired when an element has received focus. The main /// difference between this event and focusin is that only the latter bubbles. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/focus) // https://w3c.github.io/uievents/#event-type-focus #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "FocusEvent")] #[reference(event = "focus")] #[reference(subclass_of(Event, FocusRelatedEvent))] pub struct FocusEvent( Reference ); impl IEvent for FocusEvent {} impl IFocusEvent for FocusEvent {} /// The `BlurEvent` is fired when an element has lost focus. The main difference /// between this event and focusout is that only the latter bubbles. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/blur) // https://w3c.github.io/uievents/#event-type-blur #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "FocusEvent")] #[reference(event = "blur")] #[reference(subclass_of(Event, FocusRelatedEvent))] pub struct BlurEvent( Reference ); impl IEvent for BlurEvent {} impl IFocusEvent for BlurEvent {} #[cfg(all(test, feature = "web_test"))] mod tests { use super::*; use webapi::event::ConcreteEvent; #[test] fn test_focus_event() { let event: FocusEvent = js!( return new FocusEvent( "focus" ); ).try_into().unwrap(); assert_eq!( event.event_type(), "focus" ); assert!( event.related_target().is_none() ); } #[test] fn test_blur_event() { let event: BlurEvent = js!( return new FocusEvent( @{BlurEvent::EVENT_TYPE} ); ).try_into().unwrap(); assert_eq!( event.event_type(), BlurEvent::EVENT_TYPE ); } } stdweb-0.4.20/src/webapi/events/gamepad.rs010064400017500001750000000055441337463116100166310ustar0000000000000000use webcore::value::Reference; use webcore::try_from::TryInto; use webapi::event::{IEvent, Event}; use webapi::gamepad::Gamepad; /// A GamepadEvent is fired on the window object, when a gamepad is connected or disconnected to the system. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/GamepadEvent) // https://w3c.github.io/gamepad/#gamepadevent-interface pub trait IGamepadEvent: IEvent { /// Returns the gamepad associated with this event. #[inline] fn gamepad( &self ) -> Gamepad { js!( return @{self.as_ref()}.gamepad; ).try_into().unwrap() } } /// A reference to a JavaScript object which implements the [IGamepadEvent](trait.IGamepadEvent.html) /// interface. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/GamepadEvent) // https://w3c.github.io/gamepad/#gamepadevent-interface #[derive(Clone, Debug, Eq, PartialEq, ReferenceType)] #[reference(instance_of = "GamepadEvent")] #[reference(subclass_of(Event))] pub struct GamepadEvent( Reference ); impl IEvent for GamepadEvent {} impl IGamepadEvent for GamepadEvent {} /// The `GamepadConnected` event is fired on the window object, when the first input is received for a gamepad. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/gamepadconnected) // https://w3c.github.io/gamepad/#event-gamepadconnected #[derive(Clone, Debug, Eq, PartialEq, ReferenceType)] #[reference(instance_of = "GamepadEvent")] #[reference(event = "gamepadconnected")] #[reference(subclass_of(Event, GamepadEvent))] pub struct GamepadConnectedEvent( Reference ); impl IEvent for GamepadConnectedEvent {} impl IGamepadEvent for GamepadConnectedEvent {} /// The `GamepadDisconnected` event is fired on the window object, when a gamepad is disconnected. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/gamepaddisconnected) // https://w3c.github.io/gamepad/#event-gamepaddisconnected #[derive(Clone, Debug, Eq, PartialEq, ReferenceType)] #[reference(instance_of = "GamepadEvent")] #[reference(event = "gamepaddisconnected")] #[reference(subclass_of(Event, GamepadEvent))] pub struct GamepadDisconnectedEvent( Reference ); impl IEvent for GamepadDisconnectedEvent {} impl IGamepadEvent for GamepadDisconnectedEvent {} #[cfg(all(test, feature = "web_test"))] mod tests { use super::*; #[test] fn test_gamepad_connected_event() { let event: GamepadConnectedEvent = js!( return new GamepadEvent("gamepadconnected"); ).try_into().unwrap(); assert_eq!(event.event_type(), "gamepadconnected"); } #[test] fn test_gamepad_disconnected_event() { let event: GamepadDisconnectedEvent = js!( return new GamepadEvent("gamepaddisconnected"); ).try_into().unwrap(); assert_eq!(event.event_type(), "gamepaddisconnected"); } } stdweb-0.4.20/src/webapi/events/history.rs010064400017500001750000000112621351311462600167230ustar0000000000000000use webcore::value::{Reference, Value}; use webcore::try_from::TryInto; use webapi::event::{IEvent, Event}; /// The `HashChangeEvent` is fired when the fragment /// identifier of the URL has changed (the part of the URL /// that follows the # symbol, including the # symbol). /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/hashchange) // https://html.spec.whatwg.org/#event-hashchange // https://html.spec.whatwg.org/#hashchangeevent #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "HashChangeEvent")] #[reference(event = "hashchange")] #[reference(subclass_of(Event))] pub struct HashChangeEvent( Reference ); impl IEvent for HashChangeEvent {} impl HashChangeEvent { /// The previous URL from which the window was navigated. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/HashChangeEvent) // https://html.spec.whatwg.org/#the-hashchangeevent-interface:dom-hashchangeevent-oldurl #[inline] pub fn old_url( &self ) -> String { js!( return @{self.as_ref()}.oldURL; ).try_into().unwrap() } /// The new URL to which the window was navigated. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/HashChangeEvent) // https://html.spec.whatwg.org/#the-hashchangeevent-interface:dom-hashchangeevent-newurl #[inline] pub fn new_url( &self ) -> String { js!( return @{self.as_ref()}.newURL; ).try_into().unwrap() } } /// A `PopStateEvent` is dispatched to the window every time the active history entry changes /// between two history entries for the same document. If the history entry being activated was /// created by a call to `history.push_state()` or was affected by a call to /// `history.replace_state()`, the `PopStateEvent`'s state property contains a copy of the history /// entry's state object. /// /// Note that just calling `history.push_state()` or `history.replace_state()` won't trigger a /// `PopStateEvent`. The `PopStateEvent` is only triggered by doing a browser action such as a /// clicking on the back button (or calling `history.back()`). And the event is only /// triggered when the user navigates between two history entries for the same document. /// /// Browsers tend to handle the `PopStateEvent` differently on page load. Chrome and Safari always /// emit a `PopStateEvent` on page load, but Firefox doesn't. /// /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/PopStateEvent) // https://html.spec.whatwg.org/#event-popstate // https://html.spec.whatwg.org/#popstateevent #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "Event")] #[reference(event = "popstate")] #[reference(subclass_of(Event))] pub struct PopStateEvent(Reference); impl PopStateEvent { /// The state object associated to the new history entry, if that entry was created with /// push_state or affected by replace_state. /// /// Example usage: /// /// ```rust,ignore /// let state: Option = event.state().try_into().ok(); /// ``` // https://html.spec.whatwg.org/#dom-popstateevent-state #[inline] pub fn state(&self) -> Value { js!(return @{self}.state;) } } impl IEvent for PopStateEvent {} #[cfg(all(test, feature = "web_test"))] mod tests { use super::*; use webapi::event::ConcreteEvent; #[test] fn test_hash_change_event() { let event: HashChangeEvent = js!( return new HashChangeEvent( @{HashChangeEvent::EVENT_TYPE}, { oldURL: "http://test.com#foo", newURL: "http://test.com#bar" } ); ).try_into().unwrap(); assert_eq!( event.event_type(), HashChangeEvent::EVENT_TYPE ); assert_eq!( event.old_url(), "http://test.com#foo" ); assert_eq!( event.new_url(), "http://test.com#bar" ); } #[test] fn test_pop_state_event() { let event: PopStateEvent = js!( return new PopStateEvent( @{PopStateEvent::EVENT_TYPE}, { state: { color: "tomato" } } ); ).try_into().unwrap(); assert_eq!(event.event_type(), PopStateEvent::EVENT_TYPE); let state_value: Value = event.state(); let state: std::collections::BTreeMap = state_value .as_object() .unwrap() .into(); let mut expected = std::collections::BTreeMap::new(); expected.insert("color".to_string(), "tomato".into()); assert_eq!(state, expected); } } stdweb-0.4.20/src/webapi/events/keyboard.rs010064400017500001750000000246671337463116100170420ustar0000000000000000use webcore::value::Reference; use webcore::try_from::TryInto; use webapi::event::{IEvent, Event}; // Used by KeyboardEvent and MouseEvent to get the state of a modifier key. pub(crate) fn get_event_modifier_state< T: IEvent >( event: &T, key: ModifierKey ) -> bool { js!( return @{event.as_ref()}.getModifierState( @{ match key { ModifierKey::Alt => "Alt", ModifierKey::AltGr => "AltGraph", ModifierKey::CapsLock => "CapsLock", ModifierKey::Ctrl => "Control", ModifierKey::Function => "Fn", ModifierKey::FunctionLock => "FnLock", ModifierKey::Hyper => "Hyper", ModifierKey::Meta => "Meta", ModifierKey::NumLock => "NumLock", ModifierKey::OS => "OS", ModifierKey::ScrollLock => "ScrollLock", ModifierKey::Shift => "Shift", ModifierKey::Super => "Super", ModifierKey::Symbol => "Symbol", ModifierKey::SymbolLock => "SymbolLock", } } ); ).try_into().unwrap() } /// `IKeyboardEvent` objects describe a user interaction with the /// keyboard. Each event describes a key; the event type identifies /// what kind of activity was performed. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent) // https://w3c.github.io/uievents/#keyboardevent pub trait IKeyboardEvent: IEvent { /// Indicates whether the Alt key was down when this event was fired. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/altKey) // https://w3c.github.io/uievents/#ref-for-dom-keyboardevent-altkey-3 #[inline] fn alt_key( &self ) -> bool { js!( return @{self.as_ref()}.altKey; ).try_into().unwrap() } /// Returns a code value that indicates the physical key pressed on the keyboard. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code) // https://w3c.github.io/uievents/#ref-for-dom-keyboardevent-code-3 #[inline] fn code( &self ) -> String { js!( return @{self.as_ref()}.code; ).try_into().unwrap() } /// Returns whether the Ctrl key was down when this event was fired. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/ctrlKey) // https://w3c.github.io/uievents/#ref-for-dom-keyboardevent-ctrlkey-3 #[inline] fn ctrl_key( &self ) -> bool { js!( return @{self.as_ref()}.ctrlKey; ).try_into().unwrap() } /// Returns whether a modifier key was down when this event was fired. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/getModifierState) // https://w3c.github.io/uievents/#ref-for-dom-keyboardevent-getmodifierstate-19 #[inline] fn get_modifier_state( &self, key: ModifierKey ) -> bool { get_event_modifier_state( self, key ) } /// Returns whether this event was fired during composition. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/isComposing) // https://w3c.github.io/uievents/#ref-for-dom-keyboardevent-iscomposing-1 #[inline] fn is_composing( &self ) -> bool { js!( return @{self.as_ref()}.isComposing; ).try_into().unwrap() } /// Returns the location of the key on the keyboard. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/location) // https://w3c.github.io/uievents/#ref-for-dom-keyboardevent-location-1 fn location( &self ) -> KeyboardLocation { match js!( return @{self.as_ref()}.location; ).try_into().unwrap() { 0 => KeyboardLocation::Standard, 1 => KeyboardLocation::Left, 2 => KeyboardLocation::Right, 3 => KeyboardLocation::Numpad, 4 => KeyboardLocation::Mobile, 5 => KeyboardLocation::Joystick, _ => unreachable!("Unexpected KeyboardEvent.location value"), } } /// Returns the value of a key or keys pressed by the user. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key) // https://w3c.github.io/uievents/#ref-for-dom-keyboardevent-key-4 #[inline] fn key( &self ) -> String { js!( return @{self.as_ref()}.key; ).into_string().unwrap() } /// Indicates whether the Meta key was down when this event was fired. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/metaKey) // https://w3c.github.io/uievents/#ref-for-dom-keyboardevent-metakey-3 #[inline] fn meta_key( &self ) -> bool { js!( return @{self.as_ref()}.metaKey; ).try_into().unwrap() } /// Indicates whether the key is held down such that it is repeating. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/repeat) // https://w3c.github.io/uievents/#ref-for-dom-keyboardevent-repeat-1 #[inline] fn repeat( &self ) -> bool { js!( return @{self.as_ref()}.repeat; ).try_into().unwrap() } /// Indicates whether the Shift key was down when this event was fired. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/shiftKey) // https://w3c.github.io/uievents/#ref-for-dom-keyboardevent-shiftkey-3 #[inline] fn shift_key( &self ) -> bool { js!( return @{self.as_ref()}.shiftKey; ).try_into().unwrap() } } /// A modifier key on the keyboard. #[allow(missing_docs)] #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum ModifierKey { Alt, AltGr, CapsLock, Ctrl, Function, FunctionLock, Hyper, Meta, NumLock, OS, ScrollLock, Shift, Super, Symbol, SymbolLock, } /// The location on the keyboard of a key. #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum KeyboardLocation { /// The key has only one version, or the location can't be distinguished. Standard, /// The left-hand version of a key. Left, /// The right-hand version of a key. Right, /// The key was on a numeric pad. Numpad, /// The key was on a mobile device. Mobile, /// The key was on a joystick. Joystick, } /// A reference to a JavaScript object which implements the [IKeyboardEvent](trait.IKeyboardEvent.html) /// interface. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent) // https://w3c.github.io/uievents/#keyboardevent #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "KeyboardEvent")] #[reference(subclass_of(Event))] pub struct KeyboardEvent( Reference ); impl IEvent for KeyboardEvent {} impl IKeyboardEvent for KeyboardEvent {} /// The `KeyPressEvent` is fired when a key is pressed down. It's only /// fired for keys which produce a character value. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/keypress) // https://w3c.github.io/uievents/#keypress #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "KeyboardEvent")] #[reference(event = "keypress")] #[reference(subclass_of(Event, KeyboardEvent))] pub struct KeyPressEvent( Reference ); impl IEvent for KeyPressEvent {} impl IKeyboardEvent for KeyPressEvent {} /// The `KeyDownEvent` is fired when a key is pressed down. /// Unlike the `KeyPressEvent` event it's also fired for keys which /// do not produce a character value. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/keydown) // https://w3c.github.io/uievents/#event-type-keydown #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "KeyboardEvent")] #[reference(event = "keydown")] #[reference(subclass_of(Event, KeyboardEvent))] pub struct KeyDownEvent( Reference ); impl IEvent for KeyDownEvent {} impl IKeyboardEvent for KeyDownEvent {} /// The `KeyUpEvent` is fired when a key is released. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/keyup) // https://w3c.github.io/uievents/#event-type-keyup #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "KeyboardEvent")] #[reference(event = "keyup")] #[reference(subclass_of(Event, KeyboardEvent))] pub struct KeyUpEvent( Reference ); impl IEvent for KeyUpEvent {} impl IKeyboardEvent for KeyUpEvent {} #[cfg(all(test, feature = "web_test"))] mod tests { use super::*; use webapi::event::ConcreteEvent; #[test] fn test_keyboard_event() { let event: KeyboardEvent = js!( return new KeyboardEvent( @{KeyPressEvent::EVENT_TYPE}, { key: "A", code: "KeyA", location: 0, ctrlKey: true, shiftKey: false, altKey: true, metaKey: false, repeat: true, isComposing: false } ); ).try_into().unwrap(); assert!( event.alt_key() ); assert_eq!( event.code(), "KeyA" ); assert!( event.ctrl_key() ); assert!( event.get_modifier_state( ModifierKey::Alt ) ); assert!( event.get_modifier_state( ModifierKey::Ctrl ) ); assert!( !event.get_modifier_state( ModifierKey::Shift ) ); assert!( !event.is_composing() ); assert_eq!( event.location(), KeyboardLocation::Standard ); assert_eq!( event.key(), "A" ); assert!( !event.meta_key() ); assert!( event.repeat() ); assert!( !event.shift_key() ); } #[test] fn test_keypress_event() { let event: KeyPressEvent = js!( return new KeyboardEvent( @{KeyPressEvent::EVENT_TYPE} ); ).try_into().unwrap(); assert_eq!( event.event_type(), KeyPressEvent::EVENT_TYPE ); } #[test] fn test_keydown_event_is_only_constructible_from_a_keydown_event() { let event: Option< KeyDownEvent > = js!( return new KeyboardEvent( "keydown" ); ).try_into().ok(); assert!( event.is_some() ); let event: Option< KeyDownEvent > = js!( return new KeyboardEvent( "keyup" ); ).try_into().ok(); assert!( event.is_none() ); } } stdweb-0.4.20/src/webapi/events/mod.rs010064400017500001750000000002751347032716600160120ustar0000000000000000pub mod dom; pub mod drag; pub mod focus; pub mod gamepad; pub mod history; pub mod keyboard; pub mod mouse; pub mod pointer; pub mod progress; pub mod socket; pub mod slot; pub mod touch; stdweb-0.4.20/src/webapi/events/mouse.rs010064400017500001750000000563461347032716600163750ustar0000000000000000use webcore::value::Reference; use webcore::try_from::TryInto; use webapi::event_target::EventTarget; use webapi::event::{IEvent, IUiEvent, UiEvent, Event}; use webapi::events::keyboard::{ModifierKey, get_event_modifier_state}; /// The `IMouseEvent` interface represents events that occur due to the user /// interacting with a pointing device (such as a mouse). /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent) // https://w3c.github.io/uievents/#mouseevent pub trait IMouseEvent: IUiEvent { /// Returns whether the Alt key was down when this event was fired. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/altKey) // https://w3c.github.io/uievents/#ref-for-dom-mouseevent-altkey-1 #[inline] fn alt_key( &self ) -> bool { js!( return @{self.as_ref()}.altKey; ).try_into().unwrap() } /// Indicates the mouse button that fired this event. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button) // https://w3c.github.io/uievents/#ref-for-dom-mouseevent-button-1 fn button( &self ) -> MouseButton { match js!( return @{self.as_ref()}.button; ).try_into().unwrap() { 0 => MouseButton::Left, 1 => MouseButton::Wheel, 2 => MouseButton::Right, 3 => MouseButton::Button4, 4 => MouseButton::Button5, _ => unreachable!("Unexpected MouseEvent.button value"), } } /// Indicates which mouse buttons were down when this event was fired. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/buttons) // https://w3c.github.io/uievents/#ref-for-dom-mouseevent-buttons-1 fn buttons( &self ) -> MouseButtonsState { MouseButtonsState( js!( return @{self.as_ref()}.buttons; ).try_into().unwrap() ) } /// Returns the X position in the application's client area where this event occured. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/clientX) // https://w3c.github.io/uievents/#ref-for-dom-mouseevent-clientx-2 #[inline] fn client_x( &self ) -> i32 { js!( return @{self.as_ref()}.clientX; ).try_into().unwrap() } /// Returns the Y position in the application's client area where this event occured. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/clientY) // https://w3c.github.io/uievents/#ref-for-dom-mouseevent-clienty-2 #[inline] fn client_y( &self ) -> i32 { js!( return @{self.as_ref()}.clientY; ).try_into().unwrap() } /// Returns the X position on the target element where this event occured. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/offsetX) // https://drafts.csswg.org/cssom-view/#ref-for-dom-mouseevent-offsetx #[inline] fn offset_x( &self ) -> f64 { js!( return @{self.as_ref()}.offsetX; ).try_into().unwrap() } /// Returns the Y position on the target element where this event occured. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/offsetY) // https://drafts.csswg.org/cssom-view/#ref-for-dom-mouseevent-offsety #[inline] fn offset_y( &self ) -> f64 { js!( return @{self.as_ref()}.offsetY; ).try_into().unwrap() } /// Indicates whether the Ctrl key was down when this event fired. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/ctrlKey) // https://w3c.github.io/uievents/#ref-for-dom-mouseevent-ctrlkey-1 #[inline] fn ctrl_key( &self ) -> bool { js!( return @{self.as_ref()}.ctrlKey; ).try_into().unwrap() } /// Returns the current state of the specified modifier key. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/getModifierState) // https://w3c.github.io/uievents/#ref-for-dom-mouseevent-getmodifierstate-2 #[inline] fn get_modifier_state( &self, key: ModifierKey ) -> bool { get_event_modifier_state( self, key ) } /// Indicates whether the Meta key was down when this event fired. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/metaKey) // https://w3c.github.io/uievents/#ref-for-dom-mouseevent-metakey-1 #[inline] fn meta_key( &self ) -> bool { js!( return @{self.as_ref()}.metaKey; ).try_into().unwrap() } /// Returns the change in X coordinate of the pointer between this event and the previous /// MouseMove event. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/movementX) // https://w3c.github.io/pointerlock/#extensions-to-the-mouseevent-interface #[inline] fn movement_x( &self ) -> i32 { js!( return @{self.as_ref()}.movementX; ).try_into().unwrap() } /// Returns the change in Y coordinate of the pointer between this event and the previous /// MouseMove event. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/movementX) // https://w3c.github.io/pointerlock/#extensions-to-the-mouseevent-interface #[inline] fn movement_y( &self ) -> i32 { js!( return @{self.as_ref()}.movementY; ).try_into().unwrap() } /// Returns the ID of the hit region affected by the event. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/region) #[inline] fn region( &self ) -> Option< String > { js!( return @{self.as_ref()}.region; ).try_into().ok() } /// Returns the secondary target of this event, if any. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/relatedTarget) // https://w3c.github.io/uievents/#ref-for-dom-mouseevent-relatedtarget-1 #[inline] fn related_target( &self ) -> Option< EventTarget > { js!( return @{self.as_ref()}.relatedTarget; ).try_into().ok() } /// Returns the X position of the pointer in screen coordinates. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/screenX) // https://w3c.github.io/uievents/#ref-for-dom-mouseevent-screenx-1 #[inline] fn screen_x( &self ) -> i32 { js!( return @{self.as_ref()}.screenX; ).try_into().unwrap() } /// Returns the Y position of the pointer in screen coordinates. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/screenY) // https://w3c.github.io/uievents/#ref-for-dom-mouseevent-screeny-1 #[inline] fn screen_y( &self ) -> i32 { js!( return @{self.as_ref()}.screenY; ).try_into().unwrap() } /// Indicates whether the Shift key was down when this event was fired. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/shiftKey) // https://w3c.github.io/uievents/#ref-for-dom-mouseevent-shiftkey-1 #[inline] fn shift_key( &self ) -> bool { js!( return @{self.as_ref()}.shiftKey; ).try_into().unwrap() } } /// Represents buttons on a mouse during mouse events. #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum MouseButton { /// The left mouse button. Left, /// The mouse wheel/middle mouse button. Wheel, /// The right mouse button. Right, /// The fourth mouse button (browser back). Button4, /// The fifth mouse button (browser forward). Button5, // /// The sixth mouse button, or the Pen Eraser button //TODO: Eraser, } /// Represents the state of mouse buttons in a `MouseEvent`. #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct MouseButtonsState(u8); impl MouseButtonsState { /// Check if a [MouseButton](enum.MouseButton.html) is currently pressed pub fn is_down(&self, button: MouseButton) -> bool { match button { MouseButton::Left => self.0 & 0b1 != 0, MouseButton::Right => self.0 & 0b10 != 0, MouseButton::Wheel => self.0 & 0b100 != 0, MouseButton::Button4 => self.0 & 0b1000 != 0, MouseButton::Button5 => self.0 & 0b1_0000 != 0, } } } /// A reference to a JavaScript object which implements the [IMouseEvent](trait.IMouseEvent.html) /// interface. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent) // https://w3c.github.io/uievents/#mouseevent #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "MouseEvent")] #[reference(subclass_of(Event, UiEvent))] pub struct MouseEvent( Reference ); impl IEvent for MouseEvent {} impl IUiEvent for MouseEvent {} impl IMouseEvent for MouseEvent {} /// The `ClickEvent` is fired when a pointing device button (usually a /// mouse's primary button) is pressed and released on a single element. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/click) // https://w3c.github.io/uievents/#event-type-click #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "MouseEvent")] #[reference(event = "click")] #[reference(subclass_of(Event, UiEvent, MouseEvent))] pub struct ClickEvent( Reference ); impl IEvent for ClickEvent {} impl IUiEvent for ClickEvent {} impl IMouseEvent for ClickEvent {} /// The `AuxClickEvent` event is fired when a non-primary pointing device button /// (e.g. any non-left mouse button) has been pressed and released on an element. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/auxclick) // https://w3c.github.io/uievents/#event-type-auxclick #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "MouseEvent")] #[reference(event = "auxclick")] #[reference(subclass_of(Event, UiEvent, MouseEvent))] pub struct AuxClickEvent( Reference ); impl IEvent for AuxClickEvent {} impl IUiEvent for AuxClickEvent {} impl IMouseEvent for AuxClickEvent {} /// The `ContextMenuEvent` event is fired when the right button of the mouse is clicked /// (before the context menu is displayed), or when the context menu key is pressed. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/contextmenu) // https://html.spec.whatwg.org/#event-contextmenu #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "MouseEvent")] #[reference(event = "contextmenu")] #[reference(subclass_of(Event, UiEvent, MouseEvent))] pub struct ContextMenuEvent( Reference ); impl IEvent for ContextMenuEvent {} impl IUiEvent for ContextMenuEvent {} impl IMouseEvent for ContextMenuEvent {} /// The `DoubleClickEvent` is fired when a pointing device button /// (usually a mouse's primary button) is clicked twice on a single /// element. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/dblclick) // https://w3c.github.io/uievents/#event-type-dblclick #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "MouseEvent")] #[reference(event = "dblclick")] #[reference(subclass_of(Event, UiEvent, MouseEvent))] pub struct DoubleClickEvent( Reference ); impl IEvent for DoubleClickEvent {} impl IUiEvent for DoubleClickEvent {} impl IMouseEvent for DoubleClickEvent {} /// The `MouseDownEvent` is fired when a pointing device button is pressed on /// an element. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/mousedown) // https://w3c.github.io/uievents/#event-type-mousedown #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "MouseEvent")] #[reference(event = "mousedown")] #[reference(subclass_of(Event, UiEvent, MouseEvent))] pub struct MouseDownEvent( Reference ); impl IEvent for MouseDownEvent {} impl IUiEvent for MouseDownEvent {} impl IMouseEvent for MouseDownEvent {} /// The `MouseUpEvent` is fired when a pointing device button is released /// over an element. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/mouseup) // https://w3c.github.io/uievents/#event-type-mouseup #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "MouseEvent")] #[reference(event = "mouseup")] #[reference(subclass_of(Event, UiEvent, MouseEvent))] pub struct MouseUpEvent( Reference ); impl IEvent for MouseUpEvent {} impl IUiEvent for MouseUpEvent {} impl IMouseEvent for MouseUpEvent {} /// The `MouseMoveEvent` is fired when a pointing device (usually a mouse) /// is moved while over an element. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/mousemove) // https://w3c.github.io/uievents/#event-type-mousemove #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "MouseEvent")] #[reference(event = "mousemove")] #[reference(subclass_of(Event, UiEvent, MouseEvent))] pub struct MouseMoveEvent( Reference ); impl IEvent for MouseMoveEvent {} impl IUiEvent for MouseMoveEvent {} impl IMouseEvent for MouseMoveEvent {} /// The `MouseOverEvent` is fired when a pointing device (usually a mouse) /// is moved onto the element that has the listener attached or onto one of its children. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/mouseover) // https://w3c.github.io/uievents/#event-type-mouseover #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "MouseEvent")] #[reference(event = "mouseover")] #[reference(subclass_of(Event, UiEvent, MouseEvent))] pub struct MouseOverEvent( Reference ); impl IEvent for MouseOverEvent {} impl IUiEvent for MouseOverEvent {} impl IMouseEvent for MouseOverEvent {} /// The `MouseOutEvent` is fired when a pointing device (usually a mouse) /// is moved off the element that has the listener attached or off one of its children. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/mouseout) // https://w3c.github.io/uievents/#event-type-mouseout #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "MouseEvent")] #[reference(event = "mouseout")] #[reference(subclass_of(Event, UiEvent, MouseEvent))] pub struct MouseOutEvent( Reference ); impl IEvent for MouseOutEvent {} impl IUiEvent for MouseOutEvent {} impl IMouseEvent for MouseOutEvent {} /// The `MouseEnterEvent` is fired when a pointing device (usually a mouse) /// is moved over the element that has the listener attached. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/mouseenter) // https://w3c.github.io/uievents/#event-type-mouseenter #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "MouseEvent")] #[reference(event = "mouseenter")] #[reference(subclass_of(Event, UiEvent, MouseEvent))] pub struct MouseEnterEvent( Reference ); impl IEvent for MouseEnterEvent {} impl IUiEvent for MouseEnterEvent {} impl IMouseEvent for MouseEnterEvent {} /// The `MouseLeaveEvent` is fired when a pointing device (usually a mouse) /// is moved out of an element that has the listener attached to it. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/mouseleave) // https://w3c.github.io/uievents/#event-type-mouseleave #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "MouseEvent")] #[reference(event = "mouseleave")] #[reference(subclass_of(Event, UiEvent, MouseEvent))] pub struct MouseLeaveEvent( Reference ); impl IEvent for MouseLeaveEvent {} impl IUiEvent for MouseLeaveEvent {} impl IMouseEvent for MouseLeaveEvent {} /// The `MouseWheelEvent` is fired when a pointing device's wheel button (usually a mousewheel) /// is rotated over the element that has the listener attached. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/wheel) // https://w3c.github.io/uievents/#event-type-wheel #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "MouseEvent")] #[reference(event = "wheel")] #[reference(subclass_of(Event, UiEvent, MouseEvent))] pub struct MouseWheelEvent( Reference ); impl IEvent for MouseWheelEvent {} impl IUiEvent for MouseWheelEvent {} impl IMouseEvent for MouseWheelEvent {} impl MouseWheelEvent { /// The change in X of the wheel /// /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent/deltaX) // https://w3c.github.io/uievents/#dom-wheelevent-deltax pub fn delta_x(&self) -> f64 { js! ( return @{self}.deltaX; ).try_into().unwrap() } /// The change in Y of the wheel /// /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent/deltaY) // https://w3c.github.io/uievents/#dom-wheelevent-deltay pub fn delta_y(&self) -> f64 { js! ( return @{self}.deltaY; ).try_into().unwrap() } /// The change in Z of the wheel /// /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent/deltaZ) // https://w3c.github.io/uievents/#dom-wheelevent-deltaz pub fn delta_z(&self) -> f64 { js! ( return @{self}.deltaZ; ).try_into().unwrap() } /// The unit of measure of change /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent/deltaMode) // https://w3c.github.io/uievents/#dom-wheelevent-deltamode pub fn delta_mode(&self) -> MouseWheelDeltaMode { let mode: u32 = js! ( return @{self}.deltaMode; ).try_into().unwrap(); match mode { 0 => MouseWheelDeltaMode::Pixel, 1 => MouseWheelDeltaMode::Line, 2 => MouseWheelDeltaMode::Page, _ => unreachable!() } } } /// What unit of measure the mouse wheel delta is in /// /// [(JavaScipt docs)](https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent/deltaMode) #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum MouseWheelDeltaMode { /// The unit of measurement for the delta is pixels // https://w3c.github.io/uievents/#dom-wheelevent-dom_delta_pixel Pixel, /// The unit of measurement for the delta is lines // https://w3c.github.io/uievents/#dom-wheelevent-dom_delta_line Line, /// The unit of measurement for the delta is pages // https://w3c.github.io/uievents/#dom-wheelevent-dom_delta_page Page } #[cfg(all(test, feature = "web_test"))] mod tests { use super::*; use webapi::event::ConcreteEvent; #[test] fn test_mouse_event() { let event: MouseEvent = js!( return new MouseEvent( @{ClickEvent::EVENT_TYPE}, { altKey: false, button: 2, buttons: 6, clientX: 3, clientY: 4, ctrlKey: true, metaKey: false, screenX: 1, screenY: 2, shiftKey: true } ); ).try_into().unwrap(); assert_eq!( event.event_type(), ClickEvent::EVENT_TYPE ); assert_eq!( event.alt_key(), false ); assert_eq!( event.button(), MouseButton::Right ); assert!( !event.buttons().is_down( MouseButton::Left ) ); assert!( event.buttons().is_down( MouseButton::Right ) ); assert!( event.buttons().is_down( MouseButton::Wheel ) ); assert_eq!( event.client_x(), 3 ); assert_eq!( event.client_y(), 4 ); assert!( event.ctrl_key() ); assert!( !event.get_modifier_state( ModifierKey::Alt ) ); assert!( event.get_modifier_state( ModifierKey::Ctrl ) ); assert!( event.get_modifier_state( ModifierKey::Shift ) ); assert!( !event.meta_key() ); assert_eq!( event.movement_x(), 0 ); assert_eq!( event.movement_y(), 0 ); assert!( event.region().is_none() ); assert!( event.related_target().is_none() ); assert_eq!( event.screen_x(), 1 ); assert_eq!( event.screen_y(), 2 ); assert!( event.shift_key() ); } #[test] fn test_click_event() { let event: ClickEvent = js!( return new MouseEvent( @{ClickEvent::EVENT_TYPE} ); ).try_into().unwrap(); assert_eq!( event.event_type(), ClickEvent::EVENT_TYPE ); } #[test] fn test_aux_click_event() { let event: AuxClickEvent = js!( return new MouseEvent( @{AuxClickEvent::EVENT_TYPE} ); ).try_into() .unwrap(); assert_eq!( event.event_type(), AuxClickEvent::EVENT_TYPE ); } #[test] fn test_context_menu_event() { let event: ContextMenuEvent = js!( return new MouseEvent( @{ContextMenuEvent::EVENT_TYPE} ); ).try_into().unwrap(); assert_eq!( event.event_type(), ContextMenuEvent::EVENT_TYPE ); } #[test] fn test_double_click_event() { let event: DoubleClickEvent = js!( return new MouseEvent( @{DoubleClickEvent::EVENT_TYPE} ); ).try_into().unwrap(); assert_eq!( event.event_type(), DoubleClickEvent::EVENT_TYPE ); } #[test] fn test_mouse_down_event() { let event: MouseDownEvent = js!( return new MouseEvent( @{MouseDownEvent::EVENT_TYPE} ); ).try_into().unwrap(); assert_eq!( event.event_type(), MouseDownEvent::EVENT_TYPE ); } #[test] fn test_mouse_up_event() { let event: MouseUpEvent = js!( return new MouseEvent( @{MouseUpEvent::EVENT_TYPE} ); ).try_into().unwrap(); assert_eq!( event.event_type(), MouseUpEvent::EVENT_TYPE ); } #[test] fn test_mouse_move_event() { let event: MouseMoveEvent = js!( return new MouseEvent( @{MouseMoveEvent::EVENT_TYPE} ); ).try_into().unwrap(); assert_eq!( event.event_type(), MouseMoveEvent::EVENT_TYPE ); } #[test] fn test_mouse_over_event() { let event: MouseOverEvent = js!( return new MouseEvent( @{MouseOverEvent::EVENT_TYPE} ); ).try_into().unwrap(); assert_eq!( event.event_type(), MouseOverEvent::EVENT_TYPE ); } #[test] fn test_mouse_out_event() { let event: MouseOutEvent = js!( return new MouseEvent( @{MouseOutEvent::EVENT_TYPE} ); ).try_into().unwrap(); assert_eq!( event.event_type(), MouseOutEvent::EVENT_TYPE ); } #[test] fn test_mouse_enter_event() { let event: MouseEnterEvent = js!( return new MouseEvent( @{MouseEnterEvent::EVENT_TYPE} ); ).try_into() .unwrap(); assert_eq!( event.event_type(), MouseEnterEvent::EVENT_TYPE ); } #[test] fn test_mouse_leave_event() { let event: MouseLeaveEvent = js!( return new MouseEvent( @{MouseLeaveEvent::EVENT_TYPE} ); ).try_into() .unwrap(); assert_eq!( event.event_type(), MouseLeaveEvent::EVENT_TYPE ); } #[test] fn test_mouse_wheel_event() { let event: MouseWheelEvent = js!( return new MouseEvent( @{MouseWheelEvent::EVENT_TYPE} ); ).try_into() .unwrap(); assert_eq!( event.event_type(), MouseWheelEvent::EVENT_TYPE ); } } stdweb-0.4.20/src/webapi/events/pointer.rs010064400017500001750000000501401337463116100167030ustar0000000000000000use webcore::value::Reference; use webcore::try_from::TryInto; use webapi::event::{IEvent, IUiEvent, UiEvent, Event}; use webapi::events::mouse::{IMouseEvent, MouseEvent}; #[cfg(feature = "experimental_features_which_may_break_on_minor_version_bumps")] use webapi::events::mouse::MouseButton; /// The `IPointerEvent` interface represents the state of a DOM event produced by a pointer /// such as the geometry of the contact point, the device type that generated the event, the /// amount of pressure that was applied on the contact surface, etc. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent) // https://w3c.github.io/pointerevents/#pointerevent-interface // https://w3c.github.io/pointerevents/extension.html#extensions-to-the-pointerevent-interface pub trait IPointerEvent: IMouseEvent { /// Returns a unique identifier for the pointer causing the event. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/pointerId) // https://w3c.github.io/pointerevents/#dom-pointerevent-pointerid #[inline] fn pointer_id( &self ) -> i32 { js!( return @{self.as_ref()}.pointerId; ).try_into().unwrap() } /// Returns the width, in CSS pixels, of the contact geometry of the pointer. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/width) // https://w3c.github.io/pointerevents/#dom-pointerevent-width #[inline] fn width( &self ) -> f64 { js!( return @{self.as_ref()}.width; ).try_into().unwrap() } /// Returns the height, in CSS pixels, of the contact geometry of the pointer. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/height) // https://w3c.github.io/pointerevents/#dom-pointerevent-height #[inline] fn height( &self ) -> f64 { js!( return @{self.as_ref()}.height; ).try_into().unwrap() } /// Returns the normalized pressure of the pointer in the range [0, 1] /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/pressure) // https://w3c.github.io/pointerevents/#dom-pointerevent-pressure //TODO: This should return a f32, but try_into() didn't support it at the time of writing #[inline] fn pressure( &self ) -> f64 { js!( return @{self.as_ref()}.pressure; ).try_into().unwrap() } /// Returns the normalized tangential pressure of the pointer in the range [-1, 1], where 0 is /// the hardware's neutral position /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/tangentialPressure) // https://w3c.github.io/pointerevents/#dom-pointerevent-tangentialpressure //TODO: This should return a f32, but try_into() didn't support it at the time of writing #[inline] fn tangential_pressure( &self ) -> f64 { js!( return @{self.as_ref()}.tangentialPressure; ).try_into().unwrap() } /// Returns the angle, in the range of [-90, 90] degrees, between the Y-Z plane and the plane /// containing the transducer (e.g. pen stylus) and the Y axis. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/tiltX) // https://w3c.github.io/pointerevents/#dom-pointerevent-tiltx #[inline] fn tilt_x( &self ) -> i32 { js!( return @{self.as_ref()}.tiltX; ).try_into().unwrap() } /// Returns the angle, in the range of [-90, 90] degrees, between the X-Z plane and the plane /// containing the transducer (e.g. pen stylus) and the X axis. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/tiltY) // https://w3c.github.io/pointerevents/#dom-pointerevent-tilty #[inline] fn tilt_y( &self ) -> i32 { js!( return @{self.as_ref()}.tiltY; ).try_into().unwrap() } /// Returns the clockwise rotation, in the range of [0, 359] degrees, of /// the transducer (e.g. pen stylus) around it's own major axis /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/twist) // https://w3c.github.io/pointerevents/#dom-pointerevent-twist #[inline] fn twist( &self ) -> i32 { js!( return @{self.as_ref()}.twist; ).try_into().unwrap() } /// Indicates the device type that caused the event. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/pointerType) // https://w3c.github.io/pointerevents/#dom-pointerevent-pointertype #[inline] fn pointer_type( &self ) -> String { js!( return @{self.as_ref()}.pointerType; ).try_into().unwrap() } /// Indicates if the pointer represents the primary pointer of this pointer type /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/isPrimary) // https://w3c.github.io/pointerevents/#dom-pointerevent-isprimary #[inline] fn is_primary( &self ) -> bool { js!( return @{self.as_ref()}.isPrimary; ).try_into().unwrap() } /// Indicates the mouse button that fired this event. A None value indicates no change since the last PointerEvent. /// /// This function is feature-gated because it may be merged into `MouseEvent::button()` /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button) // https://w3c.github.io/pointerevents/#the-button-property #[cfg(feature = "experimental_features_which_may_break_on_minor_version_bumps")] fn button_pointer( &self ) -> Option { match js!( return @{self.as_ref()}.button; ).try_into().unwrap() { -1 => None, 0 => Some(MouseButton::Left), 1 => Some(MouseButton::Wheel), 2 => Some(MouseButton::Right), 3 => Some(MouseButton::Button4), 4 => Some(MouseButton::Button5), _ => unreachable!("Unexpected PointerEvent.button value"), } } } /// A reference to a JavaScript object which implements the [IPointerEvent](trait.IPointerEvent.html) /// interface. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent) // https://w3c.github.io/pointerevents/#pointerevent-interface #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "PointerEvent")] #[reference(subclass_of(Event, UiEvent, MouseEvent))] pub struct PointerEvent( Reference ); impl IEvent for PointerEvent {} impl IUiEvent for PointerEvent {} impl IMouseEvent for PointerEvent {} impl IPointerEvent for PointerEvent {} /// The `PointerOverEvent` is fired when a pointing device is moved into /// a element's hit test boundaries. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/pointerover) // https://w3c.github.io/pointerevents/#the-pointerover-event #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "PointerEvent")] #[reference(event = "pointerover")] #[reference(subclass_of(Event, UiEvent, MouseEvent, PointerEvent))] pub struct PointerOverEvent( Reference ); impl IEvent for PointerOverEvent {} impl IUiEvent for PointerOverEvent {} impl IMouseEvent for PointerOverEvent {} impl IPointerEvent for PointerOverEvent {} /// The `PointerEnterEvent` is fired when a pointing device is moved into /// the hit test boundaries of an element or its descendants. This event does not bubble. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/pointerenter) // https://w3c.github.io/pointerevents/#the-pointerenter-event #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "PointerEvent")] #[reference(event = "pointerenter")] #[reference(subclass_of(Event, UiEvent, MouseEvent, PointerEvent))] pub struct PointerEnterEvent( Reference ); impl IEvent for PointerEnterEvent {} impl IUiEvent for PointerEnterEvent {} impl IMouseEvent for PointerEnterEvent {} impl IPointerEvent for PointerEnterEvent {} /// The `PointerDownEvent` is fired when a pointer becomes active /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/pointerdown) // https://w3c.github.io/pointerevents/#the-pointerdown-event #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "PointerEvent")] #[reference(event = "pointerdown")] #[reference(subclass_of(Event, UiEvent, MouseEvent, PointerEvent))] pub struct PointerDownEvent( Reference ); impl IEvent for PointerDownEvent {} impl IUiEvent for PointerDownEvent {} impl IMouseEvent for PointerDownEvent {} impl IPointerEvent for PointerDownEvent {} /// The `PointerMoveEvent` is fired when a pointer changes coordinates /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/pointermove) // https://w3c.github.io/pointerevents/#the-pointermove-event #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "PointerEvent")] #[reference(event = "pointermove")] #[reference(subclass_of(Event, UiEvent, MouseEvent, PointerEvent))] pub struct PointerMoveEvent( Reference ); impl IEvent for PointerMoveEvent {} impl IUiEvent for PointerMoveEvent {} impl IMouseEvent for PointerMoveEvent {} impl IPointerEvent for PointerMoveEvent {} impl PointerMoveEvent { /// Returns the sequence of all `PointerEvent` instances that were coalesced into the dispatched `PointerMoveEvent`. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/getCoalescedEvents) // https://w3c.github.io/pointerevents/extension.html#dom-pointerevent-getcoalescedevents #[inline] pub fn get_coalesced_events( &self ) -> Vec { js!( return @{self.as_ref()}.getCoalescedEvents(); ).try_into().unwrap() } } /// The `PointerUpEvent` is fired when a pointer is no longer active /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/pointerup) // https://w3c.github.io/pointerevents/#the-pointerup-event #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "PointerEvent")] #[reference(event = "pointerup")] #[reference(subclass_of(Event, UiEvent, MouseEvent, PointerEvent))] pub struct PointerUpEvent( Reference ); impl IEvent for PointerUpEvent {} impl IUiEvent for PointerUpEvent {} impl IMouseEvent for PointerUpEvent {} impl IPointerEvent for PointerUpEvent {} /// The `PointerCancelEvent` is fired when a pointer will no longer produce events /// (for example the device is deactivated), or if the pointer starts a gesture after a pointerdown event /// (for example panning, zooming, or drag and drop) /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/pointercancel) // https://w3c.github.io/pointerevents/#the-pointercancel-event #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "PointerEvent")] #[reference(event = "pointercancel")] #[reference(subclass_of(Event, UiEvent, MouseEvent, PointerEvent))] pub struct PointerCancelEvent( Reference ); impl IEvent for PointerCancelEvent {} impl IUiEvent for PointerCancelEvent {} impl IMouseEvent for PointerCancelEvent {} impl IPointerEvent for PointerCancelEvent {} /// The `PointerOutEvent` is fired when the pointer moves out of the hit test boundaries of an element. /// This can include when a finger leaves a touch screen or a pen leaves the detectable hover range. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/pointerout) // https://w3c.github.io/pointerevents/#the-pointerout-event #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "PointerEvent")] #[reference(event = "pointerout")] #[reference(subclass_of(Event, UiEvent, MouseEvent, PointerEvent))] pub struct PointerOutEvent( Reference ); impl IEvent for PointerOutEvent {} impl IUiEvent for PointerOutEvent {} impl IMouseEvent for PointerOutEvent {} impl IPointerEvent for PointerOutEvent {} /// The `PointerLeaveEvent` is fired when the pointer moves out of the hit test boundaries /// of an element and it's descendants. This can include when a finger leaves a touch screen /// or a pen leaves the detectable hover range. This event does not bubble. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/pointerleave) // https://w3c.github.io/pointerevents/#the-pointerleave-event #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "PointerEvent")] #[reference(event = "pointerleave")] #[reference(subclass_of(Event, UiEvent, MouseEvent, PointerEvent))] pub struct PointerLeaveEvent( Reference ); impl IEvent for PointerLeaveEvent {} impl IUiEvent for PointerLeaveEvent {} impl IMouseEvent for PointerLeaveEvent {} impl IPointerEvent for PointerLeaveEvent {} /// The `GotPointerCaptureEvent` fires when an element receives pointer capture /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/gotpointercapture) // https://w3c.github.io/pointerevents/#the-gotpointercapture-event #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "PointerEvent")] #[reference(event = "gotpointercapture")] #[reference(subclass_of(Event, UiEvent, MouseEvent, PointerEvent))] pub struct GotPointerCaptureEvent( Reference ); impl IEvent for GotPointerCaptureEvent {} impl IUiEvent for GotPointerCaptureEvent {} impl IMouseEvent for GotPointerCaptureEvent {} impl IPointerEvent for GotPointerCaptureEvent {} /// The `LostPointerCaptureEvent` fires when an element loses pointer capture /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/lostpointercapture) // https://w3c.github.io/pointerevents/#the-lostpointercapture-event #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "PointerEvent")] #[reference(event = "lostpointercapture")] #[reference(subclass_of(Event, UiEvent, MouseEvent, PointerEvent))] pub struct LostPointerCaptureEvent( Reference ); impl IEvent for LostPointerCaptureEvent {} impl IUiEvent for LostPointerCaptureEvent {} impl IMouseEvent for LostPointerCaptureEvent {} impl IPointerEvent for LostPointerCaptureEvent {} /// The `PointerLockChangeEvent` fires when the pointer is locked or unlocked /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/pointerlockchange) // http://www.w3.org/TR/pointerlock/#pointerlockchange-and-pointerlockerror-events #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "Event")] #[reference(event = "pointerlockchange")] #[reference(subclass_of(Event))] pub struct PointerLockChangeEvent( Reference ); impl IEvent for PointerLockChangeEvent {} /// The `PointerLockErrorEvent` fires when an error occurs locking a pointer /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/pointerlockerror) // http://www.w3.org/TR/pointerlock/#pointerlockchange-and-pointerlockerror-events #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "Event")] #[reference(event = "pointerlockerror")] #[reference(subclass_of(Event))] pub struct PointerLockErrorEvent( Reference ); impl IEvent for PointerLockErrorEvent {} #[cfg(all(test, feature = "web_test"))] mod tests { use super::*; use webapi::event::ConcreteEvent; #[test] fn test_pointer_event() { let event: PointerMoveEvent = js!( return new PointerEvent( @{PointerMoveEvent::EVENT_TYPE}, { altKey: false, button: -1, buttons: 6, clientX: 3, clientY: 4, ctrlKey: true, metaKey: false, screenX: 1, screenY: 2, shiftKey: true, pointerId: 5, width: 8.2, height: 6.1, pressure: 0.49, tangentialPressure: -0.2, tiltX: 20, tiltY: -42, twist: 215, pointerType: "stdweb-hand-wave", isPrimary: false, } ); ).try_into().unwrap(); assert_eq!( event.event_type(), PointerMoveEvent::EVENT_TYPE ); assert_eq!( event.pointer_id(), 5 ); assert_eq!( event.width(), 8.2 ); assert_eq!( event.height(), 6.1 ); assert!( ( event.pressure() - 0.49 ).abs() < 0.00000001 ); assert!( ( event.tangential_pressure() - -0.2 ).abs() < 0.00000001 ); assert_eq!( event.tilt_x(), 20 ); assert_eq!( event.tilt_y(), -42 ); assert_eq!( event.twist(), 215 ); assert_eq!( event.pointer_type(), "stdweb-hand-wave" ); assert_eq!( event.is_primary(), false ); assert_eq!( event.get_coalesced_events().len(), 0 ); } #[test] fn test_pointer_over_event() { let event: PointerOverEvent = js!( return new PointerEvent( @{PointerOverEvent::EVENT_TYPE} ); ).try_into().unwrap(); assert_eq!( event.event_type(), PointerOverEvent::EVENT_TYPE ); } #[test] fn test_pointer_enter_event() { let event: PointerEnterEvent = js!( return new PointerEvent( @{PointerEnterEvent::EVENT_TYPE} ); ).try_into().unwrap(); assert_eq!( event.event_type(), PointerEnterEvent::EVENT_TYPE ); } #[test] fn test_pointer_down_event() { let event: PointerDownEvent = js!( return new PointerEvent( @{PointerDownEvent::EVENT_TYPE} ); ).try_into().unwrap(); assert_eq!( event.event_type(), PointerDownEvent::EVENT_TYPE ); } #[test] fn test_pointer_move_event() { let event: PointerMoveEvent = js!( return new PointerEvent( @{PointerMoveEvent::EVENT_TYPE} ); ).try_into().unwrap(); assert_eq!( event.event_type(), PointerMoveEvent::EVENT_TYPE ); } #[test] fn test_pointer_up_event() { let event: PointerUpEvent = js!( return new PointerEvent( @{PointerUpEvent::EVENT_TYPE} ); ).try_into().unwrap(); assert_eq!( event.event_type(), PointerUpEvent::EVENT_TYPE ); } #[test] fn test_pointer_cancel_event() { let event: PointerCancelEvent = js!( return new PointerEvent( @{PointerCancelEvent::EVENT_TYPE} ); ).try_into().unwrap(); assert_eq!( event.event_type(), PointerCancelEvent::EVENT_TYPE ); } #[test] fn test_pointer_out_event() { let event: PointerOutEvent = js!( return new PointerEvent( @{PointerOutEvent::EVENT_TYPE} ); ).try_into().unwrap(); assert_eq!( event.event_type(), PointerOutEvent::EVENT_TYPE ); } #[test] fn test_pointer_leave_event() { let event: PointerLeaveEvent = js!( return new PointerEvent( @{PointerLeaveEvent::EVENT_TYPE} ); ).try_into().unwrap(); assert_eq!( event.event_type(), PointerLeaveEvent::EVENT_TYPE ); } #[test] fn test_got_pointer_capture_event() { let event: GotPointerCaptureEvent = js!( return new PointerEvent( @{GotPointerCaptureEvent::EVENT_TYPE} ); ).try_into().unwrap(); assert_eq!( event.event_type(), GotPointerCaptureEvent::EVENT_TYPE ); } #[test] fn test_lost_pointer_capture_event() { let event: LostPointerCaptureEvent = js!( return new PointerEvent( @{LostPointerCaptureEvent::EVENT_TYPE} ); ).try_into().unwrap(); assert_eq!( event.event_type(), LostPointerCaptureEvent::EVENT_TYPE ); } #[test] fn test_pointer_lock_change_event() { let event: PointerLockChangeEvent = js!( return new Event( @{PointerLockChangeEvent::EVENT_TYPE} ); ).try_into().unwrap(); assert_eq!( event.event_type(), PointerLockChangeEvent::EVENT_TYPE ); } #[test] fn test_pointer_lock_error_event() { let event: PointerLockErrorEvent = js!( return new Event( @{PointerLockErrorEvent::EVENT_TYPE} ); ).try_into().unwrap(); assert_eq!( event.event_type(), PointerLockErrorEvent::EVENT_TYPE ); } } stdweb-0.4.20/src/webapi/events/progress.rs010064400017500001750000000145531337463116100170770ustar0000000000000000use webcore::value::Reference; use webcore::try_from::TryInto; use webapi::event::{IEvent, Event}; /// The `IProgressEvent` interface represents progress-related /// events. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/ProgressEvent) // https://xhr.spec.whatwg.org/#progressevent pub trait IProgressEvent: IEvent { /// Indicates whether the progress is measureable. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/ProgressEvent/lengthComputable) // https://xhr.spec.whatwg.org/#ref-for-dom-progressevent-lengthcomputable #[inline] fn length_computable( &self ) -> bool { js!( return @{self.as_ref()}.lengthComputable; ).try_into().unwrap() } /// Returns the amount of work already performed by the underlying process. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/ProgressEvent/loaded) // https://xhr.spec.whatwg.org/#ref-for-dom-progressevent-loaded #[inline] fn loaded( &self ) -> u64 { js!( return @{self.as_ref()}.loaded; ).try_into().unwrap() } /// Returns the total amount of work that the underlying process will perform. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/ProgressEvent/total) // https://xhr.spec.whatwg.org/#ref-for-dom-progressevent-total #[inline] fn total( &self ) -> u64 { js!( return @{self.as_ref()}.total; ).try_into().unwrap() } } /// A reference to a JavaScript object which implements the [IProgressEvent](trait.IProgressEvent.html) /// interface. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/ProgressEvent) // https://xhr.spec.whatwg.org/#progressevent #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "ProgressEvent")] #[reference(subclass_of(Event))] pub struct ProgressRelatedEvent( Reference ); impl IEvent for ProgressRelatedEvent {} impl IProgressEvent for ProgressRelatedEvent {} /// The `ProgressEvent` is fired to indicate that an operation is in progress. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/progress) // https://xhr.spec.whatwg.org/#event-xhr-progress #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "ProgressEvent")] #[reference(event = "progress")] #[reference(subclass_of(Event, ProgressRelatedEvent))] pub struct ProgressEvent( Reference ); impl IEvent for ProgressEvent {} impl IProgressEvent for ProgressEvent {} /// The `ProgressLoadEvent` is fired when progress has successful finished. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/load_(ProgressEvent)) // https://xhr.spec.whatwg.org/#event-xhr-load #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "ProgressEvent")] #[reference(event = "load")] #[reference(subclass_of(Event, ProgressRelatedEvent))] pub struct ProgressLoadEvent( Reference ); impl IEvent for ProgressLoadEvent {} impl IProgressEvent for ProgressLoadEvent {} /// The `LoadStartEvent` is fired when progress has begun. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/loadstart) // https://xhr.spec.whatwg.org/#event-xhr-loadstart #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "ProgressEvent")] #[reference(event = "loadstart")] #[reference(subclass_of(Event, ProgressRelatedEvent))] pub struct LoadStartEvent( Reference ); impl IEvent for LoadStartEvent {} impl IProgressEvent for LoadStartEvent {} /// The `LoadEndEvent` is fired when progress has stopped, /// e.g. after `ProgressErrorEvent`, `ProgressAbortEvent` /// or `ProgressLoadEvent` have been dispatched. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/loadend) // https://xhr.spec.whatwg.org/#event-xhr-loadend #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "ProgressEvent")] #[reference(event = "loadend")] #[reference(subclass_of(Event, ProgressRelatedEvent))] pub struct LoadEndEvent( Reference ); impl IEvent for LoadEndEvent {} impl IProgressEvent for LoadEndEvent {} /// The `ProgressAbortEvent` is fired when the progress has been aborted. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/abort_(ProgressEvent)) // https://xhr.spec.whatwg.org/#event-xhr-abort #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "ProgressEvent")] #[reference(event = "abort")] #[reference(subclass_of(Event, ProgressRelatedEvent))] pub struct ProgressAbortEvent( Reference ); impl IEvent for ProgressAbortEvent {} impl IProgressEvent for ProgressAbortEvent {} /// The `ProgressErrorEvent` is fired when the progress has failed. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/error_(ProgressEvent)) // https://xhr.spec.whatwg.org/#event-xhr-error #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "ProgressEvent")] #[reference(event = "error")] #[reference(subclass_of(Event, ProgressRelatedEvent))] pub struct ProgressErrorEvent( Reference ); impl IEvent for ProgressErrorEvent {} impl IProgressEvent for ProgressErrorEvent {} #[cfg(all(test, feature = "web_test"))] mod tests { use super::*; use webapi::event::ConcreteEvent; #[test] fn test_progress_event() { let event: ProgressEvent = js!( return new ProgressEvent( @{ProgressEvent::EVENT_TYPE}, { lengthComputable: true, loaded: 10, total: 100, } ); ).try_into().unwrap(); assert_eq!( event.event_type(), ProgressEvent::EVENT_TYPE ); assert!( event.length_computable() ); assert_eq!( event.loaded(), 10 ); assert_eq!( event.total(), 100 ); } #[test] fn test_load_start_event() { let event: LoadStartEvent = js!( return new ProgressEvent( @{LoadStartEvent::EVENT_TYPE} ); ).try_into().unwrap(); assert_eq!( event.event_type(), LoadStartEvent::EVENT_TYPE ); } #[test] fn test_load_end_event() { let event: LoadEndEvent = js!( return new ProgressEvent( @{LoadEndEvent::EVENT_TYPE} ); ).try_into().unwrap(); assert_eq!( event.event_type(), LoadEndEvent::EVENT_TYPE ); } } stdweb-0.4.20/src/webapi/events/slot.rs010064400017500001750000000011101347032716600162010ustar0000000000000000use webcore::value::Reference; use webapi::event::{IEvent, Event}; /// The `slotchange` event is fired on an HTMLSlotElement instance /// (`` element) when the node(s) contained in that slot change. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/slotchange) // https://dom.spec.whatwg.org/#mutation-observers #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "Event")] #[reference(event = "slotchange")] #[reference(subclass_of(Event))] pub struct SlotChangeEvent( Reference ); impl IEvent for SlotChangeEvent {} stdweb-0.4.20/src/webapi/events/socket.rs010064400017500001750000000221611337463116100165150ustar0000000000000000use std::fmt::Debug; use webcore::value::{Reference, Value, ConversionError}; use webcore::try_from::{TryFrom, TryInto}; use webapi::blob::Blob; use webapi::array_buffer::ArrayBuffer; use webapi::web_socket::SocketCloseCode; use webapi::event::{IEvent, Event}; /// A SocketCloseEvent is sent to clients using WebSockets when the connection is closed. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/close) // https://html.spec.whatwg.org/multipage/web-sockets.html#closeevent #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "CloseEvent")] #[reference(event = "close")] #[reference(subclass_of(Event))] pub struct SocketCloseEvent( Reference ); impl SocketCloseEvent { /// Returns the close code sent by the server. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent/code) // https://html.spec.whatwg.org/multipage/web-sockets.html#the-closeevent-interface:dom-closeevent-code #[inline] pub fn code( &self ) -> SocketCloseCode { SocketCloseCode(js!( return @{self.as_ref()}.code; ).try_into().unwrap()) } /// Returns the reason the server closed the connection. This is specific to the particular server and sub-protocol. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent/reason) // https://html.spec.whatwg.org/multipage/web-sockets.html#the-closeevent-interface:dom-closeevent-reason #[inline] pub fn reason( &self ) -> String { js!( return @{self.as_ref()}.reason; ).try_into().unwrap() } /// Returns whether or not the connection was cleanly closed. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent/wasClean) // https://html.spec.whatwg.org/multipage/web-sockets.html#the-closeevent-interface:dom-closeevent-wasclean #[inline] pub fn was_clean( &self ) -> bool { js!( return @{self.as_ref()}.wasClean; ).try_into().unwrap() } } impl IEvent for SocketCloseEvent {} /// The error event is fired when an error occurred; the exact circumstances vary, /// events by this name are used from a variety of APIs. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/error) // https://html.spec.whatwg.org/#event-error // https://html.spec.whatwg.org/multipage/web-sockets.html#handler-websocket-onerror #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "Event")] #[reference(event = "error")] #[reference(subclass_of(Event))] pub struct SocketErrorEvent( Reference ); impl IEvent for SocketErrorEvent {} /// An open event informs the target that a data connection, has been established. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/open) // https://html.spec.whatwg.org/#event-open // https://html.spec.whatwg.org/multipage/web-sockets.html#handler-websocket-onopen #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "Event")] #[reference(event = "open")] #[reference(subclass_of(Event))] pub struct SocketOpenEvent( Reference ); impl IEvent for SocketOpenEvent {} /// Represents the types of data which can be received on a web socket. Messages /// are transmitted tagged as either binary or text: text messages are always /// received as strings. Binary messages may be received as either blobs or array /// buffers as preferred by the receiver. This choice is indicated via the /// `binary_type` field on the web socket. #[derive(Debug, Clone)] pub enum SocketMessageData { /// Text message Text(String), /// Binary message received as a blob Blob(Blob), /// Binary message received as an array buffer ArrayBuffer(ArrayBuffer), } impl SocketMessageData { /// Try to receive the message as text pub fn into_text(self) -> Option { if let SocketMessageData::Text(s) = self { Some(s) } else { None } } /// Try to receive the message as a binary blob pub fn into_blob(self) -> Option { if let SocketMessageData::Blob(b) = self { Some(b) } else { None } } /// Try to receive the message as an array buffer pub fn into_array_buffer(self) -> Option { if let SocketMessageData::ArrayBuffer(b) = self { Some(b) } else { None } } } impl TryFrom for SocketMessageData { type Error = ConversionError; fn try_from(v: Value) -> Result { match v { Value::String(s) => Ok(SocketMessageData::Text(s)), Value::Reference(ref r) => { if let Ok(b) = r.clone().try_into() { Ok(SocketMessageData::Blob(b)) } else if let Ok(b) = r.clone().try_into() { Ok(SocketMessageData::ArrayBuffer(b)) } else { Err(ConversionError::Custom(format!("Unknown message event data: {:?}", r))) } }, other => Err(ConversionError::Custom(format!("Unknown message event data: {:?}", other))) } } } /// The MessageEvent interface represents a message received by a target object. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent) // https://html.spec.whatwg.org/multipage/comms.html#messageevent pub trait IMessageEvent: IEvent where >::Error: Debug { /// The type of data received with this MessageEvent type Data: TryFrom; /// The data sent by the message emitter. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent/data) // https://html.spec.whatwg.org/multipage/comms.html#the-messageevent-interface:dom-messageevent-data #[inline] fn data( &self ) -> Self::Data { js!( return @{self.as_ref()}.data; ).try_into().unwrap() } /// A string representing the origin of the message emitter. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent/origin) // https://html.spec.whatwg.org/multipage/comms.html#the-messageevent-interface:dom-messageevent-origin #[inline] fn origin( &self ) -> String { js!( return @{self.as_ref()}.origin; ).try_into().unwrap() } /// A string representing a unique ID for the event. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent/lastEventId) // https://html.spec.whatwg.org/multipage/comms.html#the-messageevent-interface:dom-messageevent-lasteventid #[inline] fn last_event_id( &self ) -> String { js!( return @{self.as_ref()}.lastEventId; ).try_into().unwrap() } /// A MessageEventSource (which can be a WindowProxy, MessagePort, or ServiceWorker object) /// representing the message emitter. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent/source) // https://html.spec.whatwg.org/multipage/comms.html#the-messageevent-interface:dom-messageevent-source #[inline] fn source( &self ) -> Option { js!( return @{self.as_ref()}.source; ).try_into().ok() } /// An array of MessagePort objects representing the ports associated with the channel the /// message is being sent through (where appropriate, e.g. in channel messaging or when sending /// a message to a shared worker). /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent/ports) // https://html.spec.whatwg.org/multipage/comms.html#the-messageevent-interface:dom-messageevent-ports #[inline] fn ports( &self ) -> Vec { js!( return @{self.as_ref()}.ports; ).try_into().unwrap() } } /// A message event informs a WebSocket object that a message has been received. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/message) // https://html.spec.whatwg.org/#event-message #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "MessageEvent")] #[reference(event = "message")] #[reference(subclass_of(Event))] pub struct SocketMessageEvent( Reference ); // https://html.spec.whatwg.org/multipage/web-sockets.html#handler-websocket-onmessage impl IMessageEvent for SocketMessageEvent { type Data = SocketMessageData; } impl IEvent for SocketMessageEvent {} #[cfg(all(test, feature = "web_test"))] mod tests { use super::*; use webapi::event::ConcreteEvent; #[test] fn test_close_event() { let event: SocketCloseEvent = js!( return new CloseEvent( @{SocketCloseEvent::EVENT_TYPE}, { code: 1000, reason: "WebSocket was closed normally", wasClean: true } ); ).try_into().unwrap(); assert_eq!( event.event_type(), SocketCloseEvent::EVENT_TYPE ); assert_eq!( event.code(), SocketCloseCode::NORMAL_CLOSURE ); assert_eq!( event.reason(), "WebSocket was closed normally" ); assert!( event.was_clean() ); } } stdweb-0.4.20/src/webapi/events/touch.rs010064400017500001750000000235001347032716600163510ustar0000000000000000use webcore::value::Reference; use webcore::try_from::TryInto; use webapi::event::{IEvent, IUiEvent, UiEvent, Event}; use webapi::touch::Touch; /// The `ITouchEvent` interface represents events that occur due to the user /// interacting with a touch device (such as a phone). /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent) // https://w3c.github.io/touch-events/#idl-def-touchevent pub trait ITouchEvent: IUiEvent { /// Returns whether the Alt key was down when this event was fired. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent/altKey) // https://w3c.github.io/touch-events/#touchevent-interface #[inline] fn alt_key( &self ) -> bool { js!( return @{self.as_ref()}.altKey; ).try_into().unwrap() } /// Indicates whether the Ctrl key was down when this event fired. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent/ctrlKey) // https://w3c.github.io/touch-events/#touchevent-interface #[inline] fn ctrl_key( &self ) -> bool { js!( return @{self.as_ref()}.ctrlKey; ).try_into().unwrap() } /// Indicates whether the Meta key was down when this event fired. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent/metaKey) // https://w3c.github.io/touch-events/#touchevent-interface #[inline] fn meta_key( &self ) -> bool { js!( return @{self.as_ref()}.metaKey; ).try_into().unwrap() } /// Indicates whether the Shift key was down when this event was fired. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent/shiftKey) // https://w3c.github.io/touch-events/#touchevent-interface #[inline] fn shift_key( &self ) -> bool { js!( return @{self.as_ref()}.shiftKey; ).try_into().unwrap() } /// A list of Touches for every point of contact currently touching the surface. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent/touches) // https://w3c.github.io/touch-events/#touchevent-interface #[inline] fn touches( &self ) -> Vec { js!( return Array.from( @{self.as_ref()}.touches ); ).try_into().unwrap() } /// A list of Touches for every point of contact that is touching the surface and started /// on the element that is the target of the current event. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent/targetTouches) // https://w3c.github.io/touch-events/#touchevent-interface #[inline] fn target_touches( &self ) -> Vec { js!( return Array.from( @{self.as_ref()}.targetTouches ); ).try_into().unwrap() } /// A list of Touches, one for each touch touch point that just became active with the current event. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent/changedTouches) // https://w3c.github.io/touch-events/#touchevent-interface #[inline] fn changed_touches( &self ) -> Vec { js!( return Array.from( @{self.as_ref()}.changedTouches ); ).try_into().unwrap() } } /// A reference to a JavaScript object which implements the [ITouchEvent](trait.ITouchEvent.html) /// interface. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent) // https://w3c.github.io/touch-events/#idl-def-touchevent #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "TouchEvent")] #[reference(subclass_of(Event, UiEvent))] pub struct TouchEvent( Reference ); impl IEvent for TouchEvent {} impl IUiEvent for TouchEvent {} impl ITouchEvent for TouchEvent {} /// The `TouchMove` is fired when one or more touch points are moved along the /// touch surface. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/touchmove) // https://w3c.github.io/touch-events/#event-touchmove #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "TouchEvent")] #[reference(event = "touchmove")] #[reference(subclass_of(Event, UiEvent, TouchEvent))] pub struct TouchMove( Reference ); impl IEvent for TouchMove {} impl IUiEvent for TouchMove {} impl ITouchEvent for TouchMove {} /// The `TouchLeave` event is fired when a touch point is moved off the /// interactive area of an element. /// /// Warning: This event was a proposal in an early version of the specification /// and has not been implemented. Do not rely on it. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/touchleave) #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "TouchEvent")] #[reference(event = "touchleave")] #[reference(subclass_of(Event, UiEvent, TouchEvent))] pub struct TouchLeave( Reference ); impl IEvent for TouchLeave {} impl IUiEvent for TouchLeave {} impl ITouchEvent for TouchLeave {} /// The `TouchEnter` event is fired when a touch point is moved onto the /// interactive area of an element. /// /// Warning: This event was a proposal in an early version of the specification /// and has not been implemented. Do not rely on it. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/touchenter) #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "TouchEvent")] #[reference(event = "touchenter")] #[reference(subclass_of(Event, UiEvent, TouchEvent))] pub struct TouchEnter( Reference ); impl IEvent for TouchEnter {} impl IUiEvent for TouchEnter {} impl ITouchEvent for TouchEnter {} /// The `TouchEnd` event is fired when one or more touch points are removed /// from the touch surface. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/touchend) // https://w3c.github.io/touch-events/#event-touchend #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "TouchEvent")] #[reference(event = "touchend")] #[reference(subclass_of(Event, UiEvent, TouchEvent))] pub struct TouchEnd( Reference ); impl IEvent for TouchEnd {} impl IUiEvent for TouchEnd {} impl ITouchEvent for TouchEnd {} /// The `TouchCancel` event is fired when one or more touch points have been /// disrupted in an implementation-specific manner (for example, too many touch /// points are created). /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/touchcancel) // https://w3c.github.io/touch-events/#event-touchcancel #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "TouchEvent")] #[reference(event = "touchcancel")] #[reference(subclass_of(Event, UiEvent, TouchEvent))] pub struct TouchCancel( Reference ); impl IEvent for TouchCancel {} impl IUiEvent for TouchCancel {} impl ITouchEvent for TouchCancel {} /// The `TouchStart` event is fired when one or more touch points are placed /// on the touch surface. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/touchstart) // https://w3c.github.io/touch-events/#event-touchstart #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "TouchEvent")] #[reference(event = "touchstart")] #[reference(subclass_of(Event, UiEvent, TouchEvent))] pub struct TouchStart( Reference ); impl IEvent for TouchStart {} impl IUiEvent for TouchStart {} impl ITouchEvent for TouchStart {} #[cfg(all(test, feature = "web_test"))] mod tests { use super::*; use webapi::event::ConcreteEvent; #[test] fn test_touch_event() { let event: TouchEvent = js!( return new TouchEvent( @{TouchMove::EVENT_TYPE}, { touches: [], targetTouches: [], changedTouches: [], ctrlKey: true, shiftKey: true, altKey: true, metaKey: true } ); ).try_into().unwrap(); assert_eq!( event.event_type(), TouchMove::EVENT_TYPE ); assert!( event.ctrl_key() ); assert!( event.alt_key() ); assert!( event.shift_key() ); assert!( event.meta_key() ); assert_eq!( event.touches(), vec![] ); assert_eq!( event.target_touches(), vec![] ); assert_eq!( event.changed_touches(), vec![] ); } #[test] fn test_touch_move_event() { let event: TouchMove = js!( return new TouchEvent( @{TouchMove::EVENT_TYPE} ); ).try_into().unwrap(); assert_eq!( event.event_type(), TouchMove::EVENT_TYPE ); } #[test] fn test_touch_leave_event() { let event: TouchLeave = js!( return new TouchEvent( @{TouchLeave::EVENT_TYPE} ); ).try_into().unwrap(); assert_eq!( event.event_type(), TouchLeave::EVENT_TYPE ); } #[test] fn test_touch_enter_event() { let event: TouchEnter = js!( return new TouchEvent( @{TouchEnter::EVENT_TYPE} ); ).try_into().unwrap(); assert_eq!( event.event_type(), TouchEnter::EVENT_TYPE ); } #[test] fn test_touch_end_event() { let event: TouchEnd = js!( return new TouchEvent( @{TouchEnd::EVENT_TYPE} ); ).try_into().unwrap(); assert_eq!( event.event_type(), TouchEnd::EVENT_TYPE ); } #[test] fn test_touch_cancel_event() { let event: TouchCancel = js!( return new TouchEvent( @{TouchCancel::EVENT_TYPE} ); ).try_into().unwrap(); assert_eq!( event.event_type(), TouchCancel::EVENT_TYPE ); } #[test] fn test_touch_start_event() { let event: TouchStart = js!( return new TouchEvent( @{TouchStart::EVENT_TYPE} ); ).try_into().unwrap(); assert_eq!( event.event_type(), TouchStart::EVENT_TYPE ); } } stdweb-0.4.20/src/webapi/file.rs010064400017500001750000000015521347032716600146450ustar0000000000000000use webcore::value::Reference; use webcore::try_from::TryInto; use webapi::blob::{IBlob, Blob}; /// The File interface provides information about files and allows JavaScript /// in a web page to access their content. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/File) // https://w3c.github.io/FileAPI/#dfn-file #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "File")] #[reference(subclass_of(Blob))] pub struct File( pub(crate) Reference ); impl IBlob for File {} impl File { /// Returns the name of the file referenced by the `File` object. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/File/name) // https://w3c.github.io/FileAPI/#ref-for-dfn-name%E2%91%A0 pub fn name( &self ) -> String { js!( return @{self}.name; ).try_into().unwrap() } } stdweb-0.4.20/src/webapi/file_list.rs010064400017500001750000000042651331624470200156750ustar0000000000000000use webcore::value::{Value, Reference}; use webcore::try_from::TryInto; use webcore::reference_type::ReferenceType; use webapi::file::File; /// An object of this type is returned by the files property of the HTML `` element; /// this lets you access the list of files selected with the `` element. /// It's also used for a list of files dropped into web content when using the drag and drop API. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/FileList) // https://w3c.github.io/FileAPI/#dfn-filelist #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "FileList")] pub struct FileList( Reference ); impl FileList { /// Returns the number of [File](struct.File.html)s contained in this list. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/FileList/length) // https://w3c.github.io/FileAPI/#ref-for-dfn-length pub fn len( &self ) -> u32 { js!( return @{self}.length; ).try_into().unwrap() } /// Returns an iterator over the list. pub fn iter( &self ) -> FileIter { FileIter { list: self.clone(), index: 0 } } } impl IntoIterator for FileList { type Item = File; type IntoIter = FileIter; #[inline] fn into_iter( self ) -> Self::IntoIter { FileIter { list: self, index: 0 } } } impl< 'a > IntoIterator for &'a FileList { type Item = File; type IntoIter = FileIter; #[inline] fn into_iter( self ) -> Self::IntoIter { FileIter { list: self.clone(), index: 0 } } } #[derive(Debug)] pub struct FileIter { list: FileList, index: i32 } impl Iterator for FileIter { type Item = File; fn next( &mut self ) -> Option< Self::Item > { let value = js!( return @{&self.list}[ @{self.index} ]; ); let file = match value { Value::Undefined => return None, Value::Reference( reference ) => unsafe { File::from_reference_unchecked( reference ) }, _ => unreachable!() }; self.index += 1; Some( file ) } } stdweb-0.4.20/src/webapi/file_reader.rs010064400017500001750000000114331331624470200161570ustar0000000000000000use webcore::value::{Value, Reference}; use webcore::try_from::TryInto; use webapi::blob::IBlob; use webapi::event_target::{IEventTarget, EventTarget}; use webapi::array_buffer::ArrayBuffer; use private::TODO; /// The FileReader object lets web applications asynchronously read the contents of files /// (or raw data buffers) stored on the user's computer, using [File](struct.File.html) /// or [Blob](struct.Blob.html) objects to specify the file or data to read. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/FileReader) // https://w3c.github.io/FileAPI/#dfn-filereader #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "FileReader")] #[reference(subclass_of(EventTarget))] pub struct FileReader( Reference ); impl IEventTarget for FileReader {} /// The [result](struct.FileReader.html#method.result) of a read operation performed with a [FileReader](struct.File.html). #[derive(Clone, Debug)] pub enum FileReaderResult { /// A string; a result of calling [FileReader::read_as_text](struct.FileReader.html#method.read_as_text). String( String ), /// An [ArrayBuffer](struct.ArrayBuffer.html); a result of calling [FileReader::read_as_array_buffer](struct.FileReader.html#method.read_as_array_buffer). ArrayBuffer( ArrayBuffer ) } /// A number indicating the state of the `FileReader`. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readyState) #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum FileReaderReadyState { /// No data has been loaded yet. Empty, /// Data is currently being loaded. Loading, /// The entire read request has been completed. Done } impl FileReader { /// Returns a newly constructed `FileReader`. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/FileReader/FileReader) // https://w3c.github.io/FileAPI/#dom-filereader-filereader pub fn new() -> FileReader { js!( return new FileReader(); ).try_into().unwrap() } /// Starts reading the contents of the specified blob. Once finished /// the `result` attribute will contain the contents of the file as a text string. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsText) // https://w3c.github.io/FileAPI/#ref-for-dfn-readAsText pub fn read_as_text< T: IBlob >( &self, blob: &T ) -> Result< (), TODO > { js!( @{self}.readAsText( @{blob.as_ref()} ); ); Ok(()) } /// Starts reading the contents of the specified blob. Once finished /// the `result` attribute will contain the contents of the file as an [TypedArray](struct.ArrayBuffer.html). /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsArrayBuffer) // https://w3c.github.io/FileAPI/#ref-for-dfn-readAsArrayBuffer pub fn read_as_array_buffer< T: IBlob >( &self, blob: &T ) -> Result< (), TODO > { js!( @{self}.readAsArrayBuffer( @{blob.as_ref()} ); ); Ok(()) } /// Aborts the read operation. Upon return, the `ready_state` will be `Done`. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/FileReader/abort) // https://w3c.github.io/FileAPI/#ref-for-dfn-abort%E2%91%A0 pub fn abort( &self ) { js!( return @{self}.abort(); ); } /// Returns the current state of the reader. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readyState) // https://w3c.github.io/FileAPI/#ref-for-dfn-readyState pub fn ready_state( &self ) -> FileReaderReadyState { let state: i32 = js!( return @{self}.readyState; ).try_into().unwrap(); match state { 0 => FileReaderReadyState::Empty, 1 => FileReaderReadyState::Loading, 2 => FileReaderReadyState::Done, _ => unreachable!( "Unexpected value of FileReader::readyState: {}", state ) } } /// The file's contents. This method will only return a value after the read operation /// is complete, and the format of the data depends on which of the methods was used /// to initiate the read operation. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/FileReader/result) // https://w3c.github.io/FileAPI/#ref-for-dfn-result pub fn result( &self ) -> Option< FileReaderResult > { let result = js!( return @{self}.result; ); match result { Value::Undefined | Value::Null => None, Value::String( text ) => Some( FileReaderResult::String( text ) ), Value::Reference( reference ) => Some( FileReaderResult::ArrayBuffer( reference.try_into().unwrap() ) ), _ => unreachable!( "Unexpected result of a FileReader: {:?}", result ) } } } stdweb-0.4.20/src/webapi/form_data.rs010064400017500001750000000214361347032716600156650ustar0000000000000000use webapi::blob::IBlob; use webapi::dom_exception::InvalidStateError; use webapi::element::IElement; use webapi::error::TypeError; use webapi::file::File; use webcore::try_from::TryFrom; use webcore::try_from::TryInto; use webcore::value::ConversionError; use webcore::value::Reference; use webcore::value::Value; /// The `FormData` interface provides a way to easily construct a set of key/value pairs /// representing form fields and their values, which can then be easily sent using the /// `XMLHttpRequest.send()` method. It uses the same format a form would use if the encoding type /// were set to `"multipart/form-data"`. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/FormData) // https://xhr.spec.whatwg.org/#formdata #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "FormData")] pub struct FormData( Reference ); /// Represents a type of data stores in FormData. #[derive(Clone, Debug, PartialEq)] pub enum FormDataEntry { /// File data File( File ), /// Text data String( String ) } error_enum_boilerplate! { FormDataFromElementError, InvalidStateError, TypeError } impl TryFrom< Value > for FormDataEntry { type Error = ConversionError; fn try_from(value: Value) -> Result< Self, Self::Error > { let entry = match value { Value::String(s) => FormDataEntry::String(s), Value::Reference(r) => FormDataEntry::File(File(r)), _ => return Err(ConversionError::type_mismatch(&value, "string or reference".into())), }; Ok(entry) } } impl TryFrom< Value > for Option< FormDataEntry > { type Error = ConversionError; fn try_from(value: Value) -> Result< Self, Self::Error > { let entry = match value { Value::Null|Value::Undefined => None, Value::String(s) => Some(FormDataEntry::String(s)), Value::Reference(r) => Some(FormDataEntry::File(File(r))), _ => return Err(ConversionError::type_mismatch(&value, "null, string or reference".into())), }; Ok(entry) } } impl FormData { /// Creates a new `FormData`. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/FormData/FormData) pub fn new() -> Self { js! ( return new FormData(); ).try_into().unwrap() } /// Creates a new `FormData` from a form element. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/FormData/FormData) pub fn from_element( form: &T ) -> Result< Self, FormDataFromElementError > where T: IElement { js_try! ( let form = @{form.as_ref()}; if ( ! (form instanceof HTMLFormElement) ) { throw new TypeError("Argument 1 of FormData::from_element does not implement interface HTMLFormElement."); } return new FormData(form); ).unwrap() } /// Appends a new value onto an existing key, or adds the key if it does not already exist. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/FormData/append) // https://xhr.spec.whatwg.org/#dom-formdata-append pub fn append_string( &self, name: &str, value: &str ) { js! { @(no_return) @{self}.append(@{name}, @{value}); } } /// Appends a new blob onto an existing key, or adds the key if it does not already exist. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/FormData/append) // https://xhr.spec.whatwg.org/#dom-formdata-append-blob pub fn append_blob( &self, name: &str, value: &T, filename: Option< &str > ) where T: IBlob { js! { @(no_return) @{self}.append(@{name}, @{value.as_ref()}, @{filename}); } } /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/FormData/delete) // https://xhr.spec.whatwg.org/#dom-formdata-delete pub fn delete( &self, name: &str ) { js! { @(no_return) @{self}.delete(@{name}); } } /// Deletes a key and its value(s). /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/FormData/get) // https://xhr.spec.whatwg.org/#dom-formdata-get pub fn get( &self, name: &str ) -> Option< FormDataEntry > { js! ( return @{self}.get(@{name}); ).try_into().unwrap() } /// Returns all the values associated with a given key. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/FormData/getAll) // https://xhr.spec.whatwg.org/#dom-formdata-getall pub fn get_all( &self, name: &str ) -> Vec< FormDataEntry > { js! ( return @{self}.getAll(@{name}); ).try_into().unwrap() } /// Returns a boolean stating whether a `FormData` object contains a certain key. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/FormData/has) // https://xhr.spec.whatwg.org/#dom-formdata-has pub fn has( &self, name: &str ) -> bool { js! ( return @{self}.has(@{name}); ).try_into().unwrap() } /// Sets a new value for an existing key, or adds the key/value if it does not already exist. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/FormData/set) // https://xhr.spec.whatwg.org/#dom-formdata-set pub fn set_string( &self, name: &str, value: &str ) { js! { @(no_return) @{self}.set(@{name}, @{value}); } } /// Sets a new blob for an existing key, or adds the key/value if it does not already exist. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/FormData/set) // https://xhr.spec.whatwg.org/#dom-formdata-set-blob pub fn set_blob( &self, name: &str, value: &T, filename: Option< &str > ) where T: IBlob { js! { @(no_return) @{self}.set(@{name}, @{value.as_ref()}, @{filename}); } } } #[cfg(all(test, feature = "web_test"))] mod tests { use stdweb::webapi::blob::Blob; use stdweb::webapi::element::Element; use stdweb::webcore::try_from::TryInto; use super::*; fn form() -> Element { js!( let form = document.createElement("form"); let inputs = []; for (let i = 1; i < 4; i++) { inputs[i] = document.createElement("input"); inputs[i].name = "key" + i; inputs[i].value = "value" + i; form.appendChild(inputs[i]); } inputs[3].name = "key2"; return form; ).try_into().unwrap() } fn data() -> FormData { let form = form(); FormData::from_element(&form) .unwrap() } #[test] fn test_new() { FormData::new(); } #[test] fn test_from_invalid_element() { use webapi::document::document; let div = document().create_element("div") .unwrap(); assert!(FormData::from_element(&div).is_err()); } #[test] fn test_append_string() { let data = data(); assert!(data.get("key0").is_none()); data.append_string("key0", "value0"); assert_eq!(data.get("key0"), Some(FormDataEntry::String(String::from("value0")))); } #[test] fn test_append_blob() { let data = data(); assert!(data.get("key0").is_none()); data.append_blob("blob", &Blob::new(), Some("file.jpg")); assert!(data.get("blob").is_some()); } #[test] fn test_delete() { let data = data(); assert!(data.get("key1").is_some()); data.delete("key1"); assert!(data.get("key1").is_none()); } #[test] fn test_get() { let data = data(); assert_eq!(data.get("key1"), Some(FormDataEntry::String(String::from("value1")))); } #[test] fn test_get_all() { let data = data(); assert_eq!(data.get_all("key2"), vec![ FormDataEntry::String(String::from("value2")), FormDataEntry::String(String::from("value3")) ]); assert_eq!(data.get_all("unknow"), Vec::::new()); } #[test] fn test_has() { let data = data(); assert_eq!(data.has("key1"), true); } #[test] fn test_set_string() { let data = data(); assert_eq!(data.get("key1"), Some(FormDataEntry::String(String::from("value1")))); data.set_string("key1", "value"); assert_eq!(data.get("key1"), Some(FormDataEntry::String(String::from("value")))); } #[test] fn test_set_blob() { let data = data(); assert_eq!(data.get("key1"), Some(FormDataEntry::String(String::from("value1")))); data.set_blob("key1", &Blob::new(), None); assert!(data.get("key1").is_some()); } } stdweb-0.4.20/src/webapi/gamepad.rs010064400017500001750000000150121337463116100153140ustar0000000000000000use webcore::try_from::{ TryFrom, TryInto, }; use webcore::value::{ ConversionError, Reference, Value, }; /// The set of known gamepad layout mappings. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Gamepad/mapping) // https://w3c.github.io/gamepad/#dom-gamepadmappingtype #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum GamepadMappingType { /// No mapping is in use for this gamepad NoMapping, /// This gamepad is mapped to the [Standard Gamepad layout](https://w3c.github.io/gamepad/#remapping) Standard, } impl TryFrom for GamepadMappingType { type Error = ConversionError; fn try_from(v: Value) -> Result { let value: String = v.try_into()?; match value.as_ref() { "" => Ok(GamepadMappingType::NoMapping), "standard" => Ok(GamepadMappingType::Standard), s => Err(ConversionError::Custom(format!("invalid gamepad mapping type \"{}\"", s))), } } } /// The state of an individual button on a gamepad device. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/GamepadButton) // https://w3c.github.io/gamepad/#gamepadbutton-interface #[derive(Clone, Debug, Eq, PartialEq, ReferenceType)] #[reference(instance_of = "GamepadButton")] pub struct GamepadButton( Reference ); impl GamepadButton { /// Is the button currently pressed? /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/GamepadButton/pressed) // https://w3c.github.io/gamepad/#dom-gamepadbutton-pressed #[inline] pub fn pressed(&self) -> bool { js!( return @{self.as_ref()}.pressed; ).try_into().unwrap() } /// Is the button currently touched? /// /// MDN does not document this. Firefox supports it, but Chrome (as of v65) does not. // https://w3c.github.io/gamepad/#dom-gamepadbutton-touched #[inline] pub fn touched(&self) -> bool { js!( return @{self.as_ref()}.touched; ).try_into().unwrap() } /// The amount which the button has been pressed, between 0.0 (not pressed), and 1.0 (fully pressed). /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/GamepadButton/value) // https://w3c.github.io/gamepad/#dom-gamepadbutton-value #[inline] pub fn value(&self) -> f64 { js!( return @{self.as_ref()}.value; ).try_into().unwrap() } } /// An individual gamepad/controller. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Gamepad) // https://w3c.github.io/gamepad/#gamepad-interface #[derive(Clone, Debug, Eq, PartialEq, ReferenceType)] #[reference(instance_of = "Gamepad")] pub struct Gamepad( Reference ); impl Gamepad { /// A string containing some information about this gamepad. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Gamepad/id) // https://w3c.github.io/gamepad/#dom-gamepad-id #[inline] pub fn id(&self) -> String { js!( return @{self.as_ref()}.id; ).try_into().unwrap() } /// An auto-incrementing integer to uniquely identify a connected Gamepad. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Gamepad/index) // https://w3c.github.io/gamepad/#dom-gamepad-index #[inline] pub fn index(&self) -> i32 { js!( return @{self.as_ref()}.index; ).try_into().unwrap() } /// Is this gamepad connected to the system, powered on, and usable? /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Gamepad/connected) // https://w3c.github.io/gamepad/#dom-gamepad-connected #[inline] pub fn connected(&self) -> bool { js!( return @{self.as_ref()}.connected; ).try_into().unwrap() } /// Monotonically increasing time this gamepad was updated. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Gamepad/timestamp) // https://w3c.github.io/gamepad/#dom-gamepad-timestamp #[inline] pub fn timestamp(&self) -> f64 { js!( return @{self.as_ref()}.timestamp; ).try_into().unwrap() } /// The mapping in use for this device. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Gamepad/mapping) // https://w3c.github.io/gamepad/#dom-gamepad-mapping #[inline] pub fn mapping(&self) -> GamepadMappingType { js!( return @{self.as_ref()}.mapping; ).try_into().unwrap() } /// Array of values for all axes of the gamepad. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Gamepad/axes) // https://w3c.github.io/gamepad/#dom-gamepad-axes #[inline] pub fn axes(&self) -> Vec { js!( return @{self.as_ref()}.axes; ).try_into().unwrap() } /// Array of button states for all buttons of the gamepad. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Gamepad/buttons) // https://w3c.github.io/gamepad/#dom-gamepad-buttons #[inline] pub fn buttons(&self) -> Vec { js!( return @{self.as_ref()}.buttons; ).try_into().unwrap() } /// Retrieve all connected gamepads, in an array indexed by each gamepad's `index` member. /// /// Chrome doesn't update Gamepad state automatically, you must call this function each frame. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/getGamepads) // https://w3c.github.io/gamepad/#dom-navigator-getgamepads pub fn get_all() -> Vec> { js!( return Array.from(navigator.getGamepads()); ).try_into().unwrap() } } #[cfg(test)] mod tests { use super::GamepadMappingType; use webcore::try_from::TryInto; use webcore::value::{ConversionError, Value}; #[test] fn test_value_into_gamepad_mapping() { let to_mapping = |v: Value| -> Result { v.try_into() }; assert_eq!(to_mapping("standard".into()), Ok(GamepadMappingType::Standard)); assert_eq!(to_mapping("".into()), Ok(GamepadMappingType::NoMapping)); assert!(to_mapping("fakemapping".into()).is_err()); assert!(to_mapping(Value::Null).is_err()); } // most of the Gamepad API is not testable, // because Gamepad and GamepadButton are not constructible } stdweb-0.4.20/src/webapi/global.rs010064400017500001750000000010751354667070600151730ustar0000000000000000use webapi::window::window; use webapi::window_or_worker::IWindowOrWorker; /// An alias for [window.set_timeout](trait.IWindowOrWorker.html#method.set_timeout). pub fn set_timeout< F: FnOnce() + 'static >( callback: F, timeout: u32 ) { window().set_timeout( callback, timeout ); } /// An alias for [window.alert](struct.Window.html#method.alert). pub fn alert( message: &str ) { window().alert( message ); } /// An alias for [window.confirm](struct.Window.html#method.confirm). pub fn confirm( message: &str ) -> bool { return window().confirm( message ); } stdweb-0.4.20/src/webapi/history.rs010064400017500001750000000110171331624470200154150ustar0000000000000000use webcore::value::Reference; use webcore::try_from::TryInto; use webcore::serialization::JsSerialize; use private::TODO; /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/History) // https://html.spec.whatwg.org/#history-3 #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "History")] pub struct History(Reference); impl History { /// Adds a new entry to history. /// /// pushState() takes three parameters: a state object, a title (which is currently ignored), /// and (optionally) a URL. Let's examine each of these three parameters in more detail: /// /// - state object — The state object is a JavaScript object which is associated with the new /// history entry created by pushState(). Whenever the user navigates to the new state, a /// popstate event is fired, and the state property of the event contains a copy of the history /// entry's state object. /// /// - title — Firefox currently ignores this parameter, although it may use it in the future. /// Passing the empty string here should be safe against future changes to the method. /// Alternatively, you could pass a short title for the state to which you're moving. /// /// - URL — The new history entry's URL is given by this parameter. Note that the browser won't /// attempt to load this URL after a call to pushState(), but it might attempt to load the URL /// later, for instance after the user restarts the browser. The new URL does not need to be /// absolute; if it's relative, it's resolved relative to the current URL. The new URL must be /// of the same origin as the current URL; otherwise, pushState() will throw an exception. /// This parameter is optional; if it isn't specified, it's set to the document's current URL. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/History_API#The_pushState%28%29_method) // https://html.spec.whatwg.org/#the-history-interface:dom-history-pushstate pub fn push_state(&self, state: T, title: &str, url: Option<&str>) { js!{ @(no_return) @{self}.pushState(@{state}, @{title}, @{url}); }; } /// Operates exactly like history.push_state() except that replace_state() modifies the current /// history entry instead of creating a new one. Note that this doesn't prevent the creation of /// a new entry in the global browser history. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/History_API#The_replaceState%28%29_method) // https://html.spec.whatwg.org/#the-history-interface:dom-history-replacestate pub fn replace_state(&self, state: T, title: &str, url: Option<&str>) -> Result< (), TODO > { js!{ @(no_return) @{self}.replaceState(@{state}, @{title}, @{url}); }; Ok(()) } /// You can use the go() method to load a specific page from session history, identified by its /// relative position to the current page (with the current page being, of course, relative /// index 0). /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/History_API#Traveling_through_history) // https://html.spec.whatwg.org/#the-history-interface:dom-history-go pub fn go(&self, offset: i32) -> Result< (), TODO > { js! { @(no_return) @{self}.go(@{offset}); }; Ok(()) } /// Move one step backward through history. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/History_API#Traveling_through_history) // https://html.spec.whatwg.org/#the-history-interface:dom-history-back pub fn back(&self) -> Result< (), TODO > { js! { @(no_return) @{self}.back(); }; Ok(()) } /// Move one step forward through history. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/History_API#Traveling_through_history) // https://html.spec.whatwg.org/#the-history-interface:dom-history-forward pub fn forward(&self) -> Result< (), TODO > { js! { @(no_return) @{self}.forward(); }; Ok(()) } /// Returns the current number of history entries. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/History) // https://html.spec.whatwg.org/#the-history-interface:dom-history-length pub fn len(&self) -> u32 { js!( return @{self}.length; ).try_into().unwrap() } } stdweb-0.4.20/src/webapi/html_collection.rs010064400017500001750000000046061331624470200171010ustar0000000000000000use webcore::value::Reference; use webcore::try_from::TryInto; use webapi::element::Element; /// The `HtmlCollection` interface represents a generic collection /// (array-like object similar to arguments) of elements (in document order) /// and offers methods and properties for selecting from the list. /// /// An `HtmlCollection` in the HTML DOM is live; it is automatically /// updated when the underlying document is changed. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCollection) // https://dom.spec.whatwg.org/#interface-htmlcollection #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "HTMLCollection")] pub struct HtmlCollection( Reference ); impl HtmlCollection { /// Returns the number of elements in the collection. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCollection) // https://dom.spec.whatwg.org/#ref-for-dom-htmlcollection-length pub fn len( &self ) -> u32 { js!( return @{self}.length; ).try_into().unwrap() } /// Returns an element from an `HtmlCollection` by index. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCollection/item) // https://dom.spec.whatwg.org/#ref-for-dom-htmlcollection-item pub fn item( &self, index: u32 ) -> Option< Element > { js!( return @{self}.item(@{index}); ).try_into().unwrap() } /// Returns an iterator over the collection. pub fn iter( &self ) -> ElementIter { ElementIter { list: self.clone(), index: 0 } } } impl IntoIterator for HtmlCollection { type Item = Element; type IntoIter = ElementIter; #[inline] fn into_iter( self ) -> Self::IntoIter { ElementIter { list: self, index: 0 } } } impl< 'a > IntoIterator for &'a HtmlCollection { type Item = Element; type IntoIter = ElementIter; #[inline] fn into_iter( self ) -> Self::IntoIter { ElementIter { list: self.clone(), index: 0 } } } #[derive(Debug)] pub struct ElementIter { list: HtmlCollection, index: u32 } impl Iterator for ElementIter { type Item = Element; fn next( &mut self ) -> Option< Self::Item > { let item = self.list.item(self.index); self.index += 1; item } } stdweb-0.4.20/src/webapi/html_element.rs010064400017500001750000000177051331624470200164030ustar0000000000000000use webcore::value::Reference; use webcore::try_from::TryInto; use webapi::event_target::{IEventTarget, EventTarget}; use webapi::node::{INode, Node}; use webapi::element::{IElement, Element}; use webapi::string_map::StringMap; /// Represents a rectangle. /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DOMRect) // https://drafts.fxtf.org/geometry-1/#domrect #[derive(Clone, Debug, ReferenceType)] #[reference(instance_of = "DOMRect")] pub struct Rect (Reference); impl Rect { /// Represents the x coordinate of the DOMRect's origin /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DOMRectReadOnly/x) // https://drafts.fxtf.org/geometry-1/#dom-domrect-x pub fn get_x( &self ) -> f64 { js! ( return @{&self.0}.x; ).try_into().unwrap() } /// Represents the y coordinate of the DOMRect's origin. /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DOMRectReadOnly/y) // https://drafts.fxtf.org/geometry-1/#dom-domrect-y pub fn get_y( &self ) -> f64 { js! ( return @{&self.0}.y; ).try_into().unwrap() } /// Represents the width of the DOMRect. /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DOMRectReadOnly/width) // https://drafts.fxtf.org/geometry-1/#dom-domrect-width pub fn get_width( &self ) -> f64 { js! ( return @{&self.0}.width; ).try_into().unwrap() } /// Represents the height of the DOMRect. /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DOMRectReadOnly/height) // https://drafts.fxtf.org/geometry-1/#dom-domrect-height pub fn get_height( &self ) -> f64 { js! ( return @{&self.0}.height; ).try_into().unwrap() } /// Returns the top coordinate value of the DOMRect. (Has the same value as y, or y + height if height is negative.) /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DOMRectReadOnly/top) // https://drafts.fxtf.org/geometry-1/#dom-domrectreadonly-top pub fn get_top( &self ) -> f64 { js! ( return @{&self.0}.top; ).try_into().unwrap() } /// Returns the right coordinate value of the DOMRect. (Has the same value as x + width, or x if width is negative.) /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DOMRectReadOnly/right) // https://drafts.fxtf.org/geometry-1/#dom-domrectreadonly-right pub fn get_right( &self ) -> f64 { js! ( return @{&self.0}.right; ).try_into().unwrap() } /// Returns the bottom coordinate value of the DOMRect. (Has the same value as y + height, or y if height is negative.) /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DOMRectReadOnly/bottom) // https://drafts.fxtf.org/geometry-1/#dom-domrectreadonly-bottom pub fn get_bottom( &self ) -> f64 { js! ( return @{&self.0}.bottom; ).try_into().unwrap() } /// Returns the left coordinate value of the DOMRect. (Has the same value as x, or x + width if width is negative.) /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/DOMRectReadOnly/left) // https://drafts.fxtf.org/geometry-1/#dom-domrectreadonly-left pub fn get_left( &self ) -> f64 { js! ( return @{&self.0}.left; ).try_into().unwrap() } } /// The `IHtmlElement` interface represents any HTML element. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement) // https://html.spec.whatwg.org/#htmlelement pub trait IHtmlElement: IElement { /// Sets focus on the specified element, if it can be focused. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus) // https://html.spec.whatwg.org/#elements-in-the-dom:dom-focus fn focus( &self ) { js! { @(no_return) @{self.as_ref()}.focus(); } } /// Removes keyboard focus from the current element. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/blur) // https://html.spec.whatwg.org/#elements-in-the-dom:dom-blur fn blur( &self ) { js! { @(no_return) @{self.as_ref()}.blur(); } } /// Allows access, both in reading and writing, to all of the custom data attributes (data-*) /// set on the element, either in HTML or in the DOM. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dataset) // https://html.spec.whatwg.org/#elements-in-the-dom:dom-dataset fn dataset( &self ) -> StringMap { unsafe { js!( return @{self.as_ref()}.dataset; ).into_reference_unchecked().unwrap() } } /// Returns the size of an element and its position relative to the viewport. /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect) // https://drafts.csswg.org/cssom-view/#ref-for-dom-element-getboundingclientrect fn get_bounding_client_rect( &self ) -> Rect { js! ( return @{self.as_ref()}.getBoundingClientRect(); ).try_into().unwrap() } /// Returns the layout width of an element. Typically, an element's offsetWidth is a /// measurement which includes the element borders, the element horizontal padding, the /// element vertical scrollbar (if present, if rendered) and the element CSS width. // https://drafts.csswg.org/cssom-view/#ref-for-dom-htmlelement-offsetwidth fn offset_width( &self ) -> i32 { js!( return @{self.as_ref()}.offsetWidth; ).try_into().unwrap() } /// Returns the height of the element including vertical padding and borders, as an /// integer. // https://drafts.csswg.org/cssom-view/#ref-for-dom-htmlelement-offsetheight fn offset_height( &self ) -> i32 { js!( return @{self.as_ref()}.offsetHeight; ).try_into().unwrap() } /// A property which represents the "rendered" text content of a node and its descendants. /// It approximates the text the user would get if they highlighted the contents of the element /// with the cursor and then copied to the clipboard. /// /// This feature was originally introduced by Internet Explorer, and was formally specified in the HTML /// standard in 2016 after being adopted by all major browser vendors. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Node/innerText) // https://html.spec.whatwg.org/#elements-in-the-dom:dom-innertext fn inner_text( &self ) -> String { js!( return @{self.as_ref()}.innerText; ).try_into().unwrap() } } /// A reference to a JavaScript object which implements the [IHtmlElement](trait.IHtmlElement.html) /// interface. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement) #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "HTMLElement")] #[reference(subclass_of(EventTarget, Node, Element))] pub struct HtmlElement( Reference ); impl IEventTarget for HtmlElement {} impl INode for HtmlElement {} impl IElement for HtmlElement {} impl IHtmlElement for HtmlElement {} #[cfg(all(test, feature = "web_test"))] mod tests { use super::*; fn div() -> Element { js!( return document.createElement("div"); ).try_into().unwrap() } fn text(text: &str) -> Node { js!( return new Text(@{text}); ).try_into().unwrap() } #[test] fn test_inner_text() { let element: HtmlElement = div().try_into().unwrap(); assert_eq!(element.inner_text(), ""); element.append_child(&text("foo ")); assert_eq!(element.inner_text(), "foo "); element.append_child(&text("foo")); assert_eq!(element.inner_text(), "foo foo"); } } stdweb-0.4.20/src/webapi/html_elements/canvas.rs010064400017500001750000000115251331624470200200330ustar0000000000000000use webcore::value::Reference; use webcore::try_from::TryInto; use webcore::once::Once; use webapi::event_target::{IEventTarget, EventTarget}; use webapi::node::{INode, Node}; use webapi::element::{IElement, Element}; use webapi::html_element::{IHtmlElement, HtmlElement}; use webapi::blob::Blob; use webapi::rendering_context::RenderingContext; use private::TODO; /// The HTML `` element provides an empty graphic zone on which specific JavaScript APIs /// can draw (such as Canvas 2D or WebGL). /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement) // https://html.spec.whatwg.org/#htmlcanvaselement #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "HTMLCanvasElement")] #[reference(subclass_of(EventTarget, Node, Element, HtmlElement))] pub struct CanvasElement( Reference ); impl IEventTarget for CanvasElement {} impl INode for CanvasElement {} impl IElement for CanvasElement {} impl IHtmlElement for CanvasElement {} impl CanvasElement { /// Returns a positive integer reflecting the height HTML attribute of the element /// interpreted in CSS pixels. When the attribute is not specified, or if it is set to an /// invalid value, like a negative, the default value of 150 is used. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/height) // https://html.spec.whatwg.org/#the-canvas-element:dom-canvas-height pub fn height( &self ) -> u32 { js! ( return @{self}.height; ).try_into().unwrap() } /// Sets a positive integer reflecting the height HTML attribute of the element /// interpreted in CSS pixels. When the attribute is not specified, or if it is set to an /// invalid value, like a negative, the default value of 150 is used. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/height) // https://html.spec.whatwg.org/#the-canvas-element:dom-canvas-height pub fn set_height( &self, value: u32 ) { js! { @(no_return) @{self}.height = @{value}; } } /// Returns a positive integer reflecting the width HTML attribute of the element /// interpreted in CSS pixels. When the attribute is not specified, or if it is set to an /// invalid value, like a negative, the default value of 300 is used. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/width) // https://html.spec.whatwg.org/#the-canvas-element:dom-canvas-width pub fn width( &self ) -> u32 { js! ( return @{self}.width; ).try_into().unwrap() } /// Sets a positive integer reflecting the width HTML attribute of the element /// interpreted in CSS pixels. When the attribute is not specified, or if it is set to an /// invalid value, like a negative, the default value of 300 is used. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/width) // https://html.spec.whatwg.org/#the-canvas-element:dom-canvas-width pub fn set_width( &self, value: u32 ) { js! { @(no_return) @{self}.width = @{value}; } } /// Returns a drawing context on the canvas, or None if the context identifier is not supported. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/getContext) // https://html.spec.whatwg.org/#the-canvas-element:dom-canvas-getcontext pub fn get_context( &self ) -> Result { T::from_canvas(self) } /// Returns a data URI containing a representation of the image in the format specified by the /// type parameter (defaults to PNG). The returned image is in a resolution of 96 dpi. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toDataUrl) // https://html.spec.whatwg.org/#the-canvas-element:dom-canvas-todataurl pub fn to_data_url( &self, mime_type: Option<&str>, quality: Option ) -> Result< String, TODO > { Ok( js! ( return @{self}.toDataURL(@{mime_type}, @{quality}); ).try_into().unwrap() ) } /// Creates a Blob object representing the image contained in the canvas; this file may be /// cached on the disk or stored in memory at the discretion of the user agent. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob) // https://html.spec.whatwg.org/#the-canvas-element:dom-canvas-toblob pub fn to_blob( &self, f: F, mime_type: Option<&str>, quality: Option ) -> Result< (), TODO > { js! { @(no_return) @{self}.toBlob(@{Once(f)}, @{mime_type}, @{quality}); } Ok(()) } } stdweb-0.4.20/src/webapi/html_elements/image.rs010064400017500001750000000256761331624470200176560ustar0000000000000000use webcore::value::{Value, Reference}; use webcore::try_from::TryInto; use webapi::cross_origin_setting::CrossOriginSetting; use webapi::event_target::{IEventTarget, EventTarget}; use webapi::node::{INode, Node}; use webapi::element::{IElement, Element}; use webapi::html_element::{IHtmlElement, HtmlElement}; /// The HTML image element is used to manipulate the layout and presentation of /// `` elements. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement) // https://html.spec.whatwg.org/#htmlimageelement #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "HTMLImageElement")] #[reference(subclass_of(EventTarget, Node, Element, HtmlElement))] pub struct ImageElement( Reference ); impl IEventTarget for ImageElement {} impl INode for ImageElement {} impl IElement for ImageElement {} impl IHtmlElement for ImageElement {} impl ImageElement { /// Constructs a new ImageElement. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/Image) // https://html.spec.whatwg.org/#the-img-element:dom-image pub fn new() -> ImageElement { js! ( return new Image(); ).try_into().unwrap() } /// Constructs a new ImageElement with the given width and height. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/Image) // https://html.spec.whatwg.org/#the-img-element:dom-image pub fn with_size(width: u32, height: u32) -> ImageElement { js! ( return new Image(@{width}, @{height}); ).try_into().unwrap() } /// Returns the HTML `alt` attribute, representing the fallback context for the image. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/alt) // https://html.spec.whatwg.org/#the-img-element:dom-img-alt #[inline] pub fn alt( &self ) -> String { js! ( return @{self}.alt; ).try_into().unwrap() } /// Sets the HTML `alt` attribute, representing the fallback context for the image. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/alt) // https://html.spec.whatwg.org/#the-img-element:dom-img-alt pub fn set_alt( &self, value: &str ) { js! { @(no_return) @{self}.alt = @{value}; } } /// Returns true if the browser has finished fetching the image, whether /// successful or not. It also return true if the image has no src value. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/complete) // https://html.spec.whatwg.org/#the-img-element:dom-img-complete pub fn complete( &self ) -> bool { js! ( return @{self}.complete; ).try_into().unwrap() } /// Returns the Cross-Origin Resource Sharing (CORS) setting for the image. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/crossOrigin) // https://html.spec.whatwg.org/#the-img-element:dom-img-crossorigin pub fn cross_origin( &self ) -> CrossOriginSetting { match js!( return @{self}.crossOrigin; ) { Value::Null => CrossOriginSetting::None, Value::String( ref s ) if *s == "anonymous" => CrossOriginSetting::Anonymous, Value::String( ref s ) if *s == "use-credentials" => CrossOriginSetting::UseCredentials, _ => unreachable!("Unexpected crossOrigin value") } } /// Sets the Cross-Origin Resource Sharing (CORS) setting for the image. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/crossOrigin) // https://html.spec.whatwg.org/#the-img-element:dom-img-crossorigin pub fn set_cross_origin( &self, value: CrossOriginSetting ) { js! { @(no_return) @{self}.crossOrigin = @{ match value { CrossOriginSetting::None => None, CrossOriginSetting::Anonymous => Some("anonymous"), CrossOriginSetting::UseCredentials => Some("use-credentials") } } } } /// Returns the the rendered height of the image in CSS pixels. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/height) // https://html.spec.whatwg.org/#the-img-element:dom-img-height pub fn height( &self ) -> u32 { js! ( return @{self}.height; ).try_into().unwrap() } /// Sets the the rendered height of the image in CSS pixels. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/height) // https://html.spec.whatwg.org/#the-img-element:dom-img-height pub fn set_height( &self, value: u32 ) { js! { @(no_return) @{self}.height = @{value}; } } /// Indicates whether the image is part of a server-side image map. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/isMap) // https://html.spec.whatwg.org/#the-img-element:dom-img-ismap pub fn is_map( &self ) -> bool { js!( return @{self}.isMap; ).try_into().unwrap() } /// Sets whether the image is part of a server-side image map. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/isMap) // https://html.spec.whatwg.org/#the-img-element:dom-img-ismap pub fn set_is_map( &self, value: bool ) { js! { @(no_return) @{self}.isMap = @{value}; } } /// Returns the intrinsic height of the image in CSS pixels, if it is available. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/naturalHeight) // https://html.spec.whatwg.org/#the-img-element:dom-img-naturalheight pub fn natural_height( &self ) -> Option< u32 > { match js!( return @{self}.naturalHeight; ).try_into().unwrap() { 0 => None, value => Some( value ) } } /// Returns the intrinsic width of the image in CSS pixels, if it is available. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/naturalWidth) // https://html.spec.whatwg.org/#the-img-element:dom-img-naturalwidth pub fn natural_width( &self ) -> Option< u32 > { match js!( return @{self}.naturalWidth; ).try_into().unwrap() { 0 => None, value => Some( value ) } } /// Returns the full URL of the image, including the base URI. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/src) // https://html.spec.whatwg.org/#the-img-element:dom-img-src pub fn src( &self ) -> String { js! ( return @{self}.src; ).try_into().unwrap() } /// Sets the full URL of the image, including the base URI. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/src) // https://html.spec.whatwg.org/#the-img-element:dom-img-src pub fn set_src( &self, value: &str ) { js! { @(no_return) @{self}.src = @{value}; } } /// Returns the `usemap` HTML attribute, containing a partial URL of a map element. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/useMap) // https://html.spec.whatwg.org/#the-img-element:dom-img-usemap pub fn use_map( &self ) -> String { js!( return @{self}.useMap; ).try_into().unwrap() } /// Sets the `usemap` HTML attribute, containing a partial URL of a map element. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/useMap) // https://html.spec.whatwg.org/#the-img-element:dom-img-usemap pub fn set_use_map( &self, value: &str ) { js! { @(no_return) @{self}.useMap = @{value}; } } /// Returns the rendered width of the image in CSS pixels. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/width) // https://html.spec.whatwg.org/#the-img-element:dom-img-width pub fn width( &self ) -> u32 { js! ( return @{self}.width; ).try_into().unwrap() } /// Sets the rendered width of the image in CSS pixels. /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/width) // https://html.spec.whatwg.org/#the-img-element:dom-img-width pub fn set_width( &self, value: u32 ) { js! { @(no_return) @{self}.width = @{value}; } } } #[cfg(all(test, feature = "web_test"))] mod tests { use super::*; #[test] fn test_new() { let image = ImageElement::new(); assert_eq!(image.alt(), ""); } #[test] fn test_with_size() { let image = ImageElement::with_size(333, 444); assert_eq!(image.width(), 333); assert_eq!(image.height(), 444); } #[test] fn test_alt() { let image = ImageElement::new(); assert_eq!(image.alt(), ""); image.set_alt("test"); assert_eq!(image.alt(), "test"); } #[test] fn test_complete() { let image = ImageElement::new(); assert_eq!(image.complete(), true); } #[test] fn test_width_height() { let image = ImageElement::new(); assert_eq!(image.width(), 0); assert_eq!(image.height(), 0); image.set_width(4); image.set_height(5); assert_eq!(image.width(), 4); assert_eq!(image.height(), 5); } #[test] fn test_src() { let image = ImageElement::new(); assert_eq!(image.src(), ""); image.set_src("http://example.com/image.gif"); assert_eq!(image.src(), "http://example.com/image.gif"); } #[test] fn test_use_map() { let image = ImageElement::new(); assert_eq!(image.use_map(), ""); image.set_use_map("test"); assert_eq!(image.use_map(), "test"); } #[test] fn test_natural_width_height() { let image = ImageElement::new(); assert_eq!(image.natural_width(), None); assert_eq!(image.natural_height(), None); } #[test] fn test_cross_origin() { let image = ImageElement::new(); assert_eq!(image.cross_origin(), CrossOriginSetting::None); image.set_cross_origin(CrossOriginSetting::Anonymous); assert_eq!(image.cross_origin(), CrossOriginSetting::Anonymous); image.set_cross_origin(CrossOriginSetting::UseCredentials); assert_eq!(image.cross_origin(), CrossOriginSetting::UseCredentials); image.set_cross_origin(CrossOriginSetting::None); assert_eq!(image.cross_origin(), CrossOriginSetting::None); } } stdweb-0.4.20/src/webapi/html_elements/input.rs010064400017500001750000000062271354113403500177170ustar0000000000000000use webcore::value::Reference; use webcore::try_from::TryInto; use webapi::dom_exception::InvalidStateError; use webapi::event_target::{IEventTarget, EventTarget}; use webapi::node::{INode, Node}; use webapi::element::{IElement, Element}; use webapi::html_element::{IHtmlElement, HtmlElement}; /// The HTML input element is used to create interactive controls /// for web-based forms in order to accept data from the user. /// /// [(JavaScript docs)](https://developer.mozilla.org/en/docs/Web/HTML/Element/input) // https://html.spec.whatwg.org/#htmlinputelement #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)] #[reference(instance_of = "HTMLInputElement")] #[reference(subclass_of(EventTarget, Node, Element, HtmlElement))] pub struct InputElement( Reference ); impl IEventTarget for InputElement {} impl INode for InputElement {} impl IElement for InputElement {} impl IHtmlElement for InputElement {} impl InputElement { /// The value of the control. This attribute is optional except when the input is a radio button or a checkbox. /// // https://html.spec.whatwg.org/#the-input-element:dom-input-value #[inline] pub fn raw_value( &self ) -> String { js! ( return @{self}.value; ).try_into().unwrap() } /// Sets the value of the control. /// // https://html.spec.whatwg.org/#dom-input-value #[inline] pub fn set_raw_value( &self, value: &str ) { js! { @(no_return) @{self}.value = @{value}; } } /// The offset to the start of the selection. /// This attribute only applies when the input is a text, search, url, telephone or password. /// // https://html.spec.whatwg.org/#the-input-element:dom-textarea/input-selectionstart #[inline] pub fn selection_start( &self ) -> Option { js! ( return @{self}.selectionStart; ).try_into().ok() } /// Sets the offset to the start of the selection. /// This attribute only applies when the input is a text, search, url, telephone or password. /// // https://html.spec.whatwg.org/#the-input-element:dom-textarea/input-selectionstart #[inline] pub fn set_selection_start( &self, value: u32 ) -> Result<(), InvalidStateError> { js_try! ( @(no_return) @{self}.selectionStart = @{value}; ).unwrap() } /// The offset to the end of the selection. /// This attribute only applies when the input is a text, search, url, telephone or password. /// // https://html.spec.whatwg.org/#the-input-element:dom-textarea/input-selectionstart #[inline] pub fn selection_end( &self ) -> Option { js! ( return @{self}.selectionEnd; ).try_into().ok() } /// Sets the offset to the end of the selection. /// This attribute only applies when the input is a text, search, url, telephone or password. /// // https://html.spec.whatwg.org/#the-input-element:dom-textarea/input-selectionstart #[inline] pub fn set_selection_end( &self, value: u32 ) -> Result<(), InvalidStateError> { js_try! ( @(no_return) @{self}.selectionEnd = @{value}; ).unwrap() } } stdweb-0.4.20/src/webapi/html_elements/mod.rs010064400017500001750000000007061347032716600173450ustar0000000000000000mod canvas; mod image; mod input; mod textarea; mod select; mod option; mod template; mod slot; pub use self::canvas::CanvasElement; pub use self::image::ImageElement; pub use self::input::InputElement; pub use self::textarea::TextAreaElement; pub use self::select::SelectElement; pub use self::option::OptionElement; pub use self::template::TemplateElement; pub use self::slot::{SlotElement, SlotContentKind}; pub use self::select::UnknownValueError; stdweb-0.4.20/src/webapi/html_elements/option.rs010064400017500001750000000031561347032716600201000ustar0000000000000000use webapi::element::{Element, IElement}; use webapi::event_target::{EventTarget, IEventTarget}; use webapi::html_element::{HtmlElement, IHtmlElement}; use webapi::node::{INode, Node}; use webcore::try_from::TryInto; use webcore::value::Reference; /// The HTML `