Giter Site home page Giter Site logo

stdweb's Introduction

Build Status Join the chat at https://gitter.im/stdweb-rs/stdweb

A standard library for the client-side Web

Documentation

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

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:

let message = "Hello, 世界!";
let result = js! {
    alert( @{message} );
    return 2 + 2 * 2;
};

println!( "2 + 2 * 2 = {:?}", result );

Closures are also supported:

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:

#[derive(Serialize)]
struct Person {
    name: String,
    age: i32
}

js_serializable!( Person );

js! {
    var person = @{person};
    console.log( person.name + " is " + person.age + " years old." );
};

This crate also exposes a number of Web APIs, for example:

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:

#[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:

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:

<script src="hasher.js"></script>
<script>
    Rust.hasher.then( function( hasher ) {
        console.log( hasher.hash( "Hello world!" ) );
    });
</script>

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:

import hasher from "./hasher/Cargo.toml";
console.log( hasher.hash( "Hello world!" ) );

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

The API documentation is also available for you to look at.

Running the examples

  1. Install cargo-web:

    $ cargo install -f cargo-web
    
  2. 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
      
  3. 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!

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
    • &Arrays can now be converted to Vecs 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
    • Values 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 TypedArrays from Vecs and ArrayBuffers.
  • 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 References
    • (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

at your option.

Snippets of documentation which come from Mozilla Developer Network are covered under the CC-BY-SA, version 2.5 or later.

Contributing

See CONTRIBUTING.md

stdweb's People

Contributors

carlosdp avatar chpio avatar daboross avatar diggsey avatar gabisurita avatar gliheng avatar herschel avatar iirelu avatar keeslinp avatar kngwyu avatar koute avatar kzvi avatar loyd avatar maudnals avatar michiel-de-muynck avatar mrdziuban avatar nico-abram avatar pajn avatar pauan avatar pepsighan avatar rickycodes avatar ryanisaacg avatar sanpii avatar siler avatar srjek avatar tacklebox avatar teovoinea avatar therustmonk avatar tomhoule avatar vitiral avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

stdweb's Issues

exception thrown: TypeError: Cannot read property 'from_js' of undefined,TypeError: Cannot read property 'from_js' of undefined

Thank you for the library, it looks very exiting! Unfortunately I am getting an error, trying to run a very simple example.

Here is my src/main.rs:

#[macro_use]
extern crate stdweb;

fn main() {
    let message = "Saluton";
    js! {
        alert( @{message} );
    };
}

In browser (both Chromium and the latest Firefox) I am getting the following errors:

http://[::1]:8000/js/app.js:190 exception thrown: TypeError: Cannot read property 'from_js' of undefined,TypeError: Cannot read property 'from_js' of undefined
    at Array.ASM_CONSTS (http://[::1]:8000/js/app.js:1602:35)
    at _emscripten_asm_const_iii (http://[::1]:8000/js/app.js:1609:26)
    at Array.__ZN6tryweb4main17he5640be6c1e443adE (http://[::1]:8000/js/app.js:8108:11)
    at __ZN3std10sys_common9backtrace28__rust_begin_short_backtrace17hf69b2510974d151bE (http://[::1]:8000/js/app.js:17305:28)
    at Array.__ZN3std9panicking3try7do_call17hc7f54292c4f8bc7dE_llvm_E2C4E477 (http://[::1]:8000/js/app.js:15004:2)
    at Object.dynCall_vi (http://[::1]:8000/js/app.js:37926:31)
    at invoke_vi (http://[::1]:8000/js/app.js:5322:25)
    at ___rust_maybe_catch_panic (http://[::1]:8000/js/app.js:24679:2)
    at __ZN3std2rt10lang_start17h24169098a28de597E (http://[::1]:8000/js/app.js:12472:9)
    at _main (http://[::1]:8000/js/app.js:8032:8)

However println!("message") results into normal console log message.

Extra details:

  • browser - the latest firefox
  • I run the app with cargo web start
  • rustc 1.24.0-nightly (dc39c3169 2017-12-17)

Idea: track reference counts on rust side

Currently the javascript runtime maps references to IDs and also maps IDs to reference counts. Whenever a Reference is cloned, the code must call out to javascript to update the reference count.

It should be possible to move the reference count onto the rust side: the javascript maps references to IDs, and then rust maps IDs to reference counts. This should make Reference as cheap to clone as a normal Rc.

When objects are serialised from javascript into rust, the rust side would be expected to increment the reference counts to avoid the javascript runtime having to perform additional calls into rust.

Handling promises

Is passing rust closures the only way to handle async stuff?
e.g. is it possible to do something like this:

    let promise = js!{
        return fetch(@{url})
            .then(response => response.text());
    };
    // unwrap promise somehow?

Refactor events file

Putting all the events in one file is already becoming quite unmanageable. It should be split out into a directory with a file for each event interface. I would open a PR but the potential for merge conflicts is quite high 😛

Document the WebAssembly story

As far as I can tell this library currently does not support wasm. But since Rust now supports wasm on stable it would be useful if documentation existed somewhere detailing this libraries future plans for supporting wasm, or if it already does and I missed that, there should be docs on how to use this library with wasm.

Edit: After fiddling a bit, I have determined that at the very least the todomvc example can run under wasm. This just means that it is unclear if wasm is actually supported or if this is something that is not guarenteed to work going forward.

Accessing JS arrays from Rust

According to the documentation it is possible to convert a Rust Vector into JavaScript arrays.

I wasn't able to find any documentation on how to do that the other way around e.g. iterate a JS array or possibly convert it into a Rust vector if possible (obviously requires that all array entries can be converted to the same type).

Trying to pass an Array to Rust

fn print_vec(vec: stdweb::Array) {
    let x: Vec<stdweb::Value> = Vec::from(&vec);
    println!("This is a vector: {:?}", x);
}

fn main() {
    stdweb::initialize();

    js! {
        Module.exports.printArray = @{print_vec};
    }
}
const vector = require( './target/wasm32-unknown-unknown/release/vector.js' );
vector..printArray([1, 2, 3, 4]);

I get the following error twice:

error[E0277]: the trait bound `stdweb::Array: stdweb::unstable::TryFrom<stdweb::Value>` is not satisfied
  --> src/main.rs:21:5
   |
21 | /     js! {
22 | |         Module.exports.printArray = @{print_vec};
23 | |     }
   | |_____^ the trait `stdweb::unstable::TryFrom<stdweb::Value>` is not implemented for `stdweb::Array`

   = note: required because of the requirements on the impl of `stdweb::private::JsSerializableOwned` for `stdweb::private::Newtype<(stdweb::webcore::serialization::FunctionTag, (stdweb::Array,)), fn(stdweb::Array) {print_vec}>`
   = note: required by `stdweb::private::JsSerializableOwned::memory_required_owned`
   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

Use error-chain

I recognized that a most parts of the api either panic! or return an Option<T>. Option<T> should only be used when there legitimately might be nothing to return. In any other case I would suggest to use the Result<T> that the error-chain crate offers.

I wouldn't use the actual chaining feature of the crate in tight loops as this can lead to severe performance issues.

I would like to implement this myself if it is a wanted feature. The error-chain crate also is very well maintained and already found a good adoption rate in the Rust community.

call a FnOnce closure in js

Hi, I need to call a FnOnce closure in js. Basicly, I used a oneshot future from futures library, and I need to move the transmiter to js side.

It looks like in the current implementation I can't do that. Here's a small useless demo.

use std::mem;
fn main() {
    stdweb::initialize();
    let v = vec![1, 2, 3];
    let call = move || {
        mem::drop(v);
    };
    js! {
        let call = @{call};
        call();
    }
    stdweb::event_loop();
}

This compiles with error:
expected a closure that implements the FnMut trait, but this closure only implements FnOnce

Any idea, I can make this happen?

Cannot pass Option<FnMut *> into js!

This works:

js! {
    var callback = @{move || { return true }};
};

While this one doesn't:

js! {
    var callback = @{Some(move || { return true })};
};

Drag and Drop API

I want to use the HTML Drag and Drop API. I'm guessing that like geolocation this just needs an implementation added.

I think to do this I need to implement

Is this all correct and would a pull request be welcome? If so I will start working on it.

Export emscripten_set_main_loop()

I'm trying to use a modified version of this guide to run an SDL app. Looks like I'm hitting the condition where SDL's event loop blocks the entire browser, so I need to tell emscripten about it.

It looks like you define this function in the crate, but it is private. Any reason it isn't exported? Is there currently an alternative way of getting at this functionality?

Note that I'm pretty new to all of this, so I don't really understand the requirements beyond suspecting that SDL's and Emxcripten's main loops don't play well together, I suppose. :)

Thanks.

Chrome / Firefox Extension APIs

There are Chrome and Firefox extension APIs which I would like to use.

Should they be added to this repo, or to a separate repo? If it's okay to add them to this repo, then I'll send some pull requests implementing them. I have a lot of experience using those APIs, so I know how to work around some bugs/quirks in them.

However, almost all of the extension APIs are asynchronous, so stdweb will need good Promise support first.

Also, ideally we should be able to write extensions that can work on either Chrome or Firefox. That could be accomplished either with runtime polyfills, or with conditional compilation within Rust.

linking failed

Hi, bellow code can't compile:

#[macro_use]
extern crate stdweb;

fn main() {
    let message = "hello world";
    let result = js! {
        alert(@{message});
        return 2 + 2 * 2;
    };
    println!("2 + 2 * 2 = {:?}", result);
}

with windows 10 throws:

linking with `link.exe` failed: exit code: 1120
...

with macOS throws:

inking with `cc` failed: exit code: 1
...

what is the problem?
thanks.

Media events & related stuff

Wow, stdweb is looking really amazing! I'm impressed at how quickly this has developed, and I've been enjoying experimenting with *.wasm code for "headless" computational tasks. But I'd like to try and port over one of my HTML-related media projects, possibly using a framework like yew.

To do this, I would need the HTML media events, and probably some related stuff, such as methods and properties on <video> and <audio>. I'd like to try my hand at it.

Would you be interested in a PR? Any advice for anybody who wants to just dive in?

`cargo web start` for `examples/todomvc` fails (with linking errors?)

Here is my log:

.../stdweb/examples/todomvc$ rustc --version
rustc 1.20.0 (f3d6973f4 2017-08-27)

.../stdweb/examples/todomvc$ rustup target add asmjs-unknown-emscripten
info: component 'rust-std' for target 'asmjs-unknown-emscripten' is up to date

.../stdweb/examples/todomvc$ cargo web start      
   Compiling todomvc v0.1.0 (file:///home/jeehoonkang/Works/stdweb/examples/todomvc)
error: linking with `emcc` failed: exit code: 1
  |
  = note: "emcc" "-s" "DISABLE_EXCEPTION_CATCHING=0" "-L" "/home/jeehoonkang/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/asmjs-unknown-emscripten/lib" "/home/jeehoonkang/Works/stdweb/examples/todomvc/target/asmjs-unknown-emscripten/debug/deps/todomvc-ba8d241b27b1f96a.0.o" "-o" "/home/jeehoonkang/Works/stdweb/examples/todomvc/target/asmjs-unknown-emscripten/debug/deps/todomvc-ba8d241b27b1f96a.js" "-s" "EXPORTED_FUNCTIONS=[\"_main\",\"___rdl_shrink_in_place\",\"___rdl_alloc_excess\",\"___rdl_usable_size\",\"___rdl_alloc\",\"___rdl_realloc_excess\",\"___rdl_realloc\",\"___rdl_oom\",\"___rdl_grow_in_place\",\"___rdl_alloc_zeroed\",\"___rdl_dealloc\",\"_rust_eh_personality\"]" "/home/jeehoonkang/Works/stdweb/examples/todomvc/target/asmjs-unknown-emscripten/debug/deps/todomvc-ba8d241b27b1f96a.crate.allocator.o" "-O0" "--memory-init-file" "0" "-g4" "-s" "DEFAULT_LIBRARY_FUNCS_TO_INCLUDE=[]" "-L" "/home/jeehoonkang/Works/stdweb/examples/todomvc/target/asmjs-unknown-emscripten/debug/deps" "-L" "/home/jeehoonkang/Works/stdweb/examples/todomvc/target/debug/deps" "-L" "/home/jeehoonkang/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/asmjs-unknown-emscripten/lib" "/home/jeehoonkang/Works/stdweb/examples/todomvc/target/asmjs-unknown-emscripten/debug/deps/libstdweb-9d820816a3b1fe1c.rlib" "/home/jeehoonkang/Works/stdweb/examples/todomvc/target/asmjs-unknown-emscripten/debug/deps/libserde_json-2e6a65e2f75759e0.rlib" "/home/jeehoonkang/Works/stdweb/examples/todomvc/target/asmjs-unknown-emscripten/debug/deps/libdtoa-49eaf858ed5bb53b.rlib" "/home/jeehoonkang/Works/stdweb/examples/todomvc/target/asmjs-unknown-emscripten/debug/deps/libnum_traits-379830a7c273381b.rlib" "/home/jeehoonkang/Works/stdweb/examples/todomvc/target/asmjs-unknown-emscripten/debug/deps/libserde-c29e90fe3a0f30b7.rlib" "/home/jeehoonkang/Works/stdweb/examples/todomvc/target/asmjs-unknown-emscripten/debug/deps/libitoa-9afcb23e92bf9413.rlib" "/home/jeehoonkang/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/asmjs-unknown-emscripten/lib/libstd-881b9fdbdf1d515b.rlib" "/home/jeehoonkang/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/asmjs-unknown-emscripten/lib/liballoc_system-3c10208cdd7e61cb.rlib" "/home/jeehoonkang/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/asmjs-unknown-emscripten/lib/librand-32f648f7f7567c6c.rlib" "/home/jeehoonkang/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/asmjs-unknown-emscripten/lib/libpanic_unwind-9cbadc6554202be9.rlib" "/home/jeehoonkang/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/asmjs-unknown-emscripten/lib/libunwind-618c266cf9124966.rlib" "/home/jeehoonkang/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/asmjs-unknown-emscripten/lib/liblibc-16f3b02b9a976b94.rlib" "/home/jeehoonkang/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/asmjs-unknown-emscripten/lib/liballoc-bc70b4efeaeb398c.rlib" "/home/jeehoonkang/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/asmjs-unknown-emscripten/lib/libstd_unicode-a0ad42dc8f5856aa.rlib" "/home/jeehoonkang/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/asmjs-unknown-emscripten/lib/libcore-21491ce3d14f1ef2.rlib" "/home/jeehoonkang/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/asmjs-unknown-emscripten/lib/libcompiler_builtins-b9713bd7f605c0b2.rlib" "-l" "c" "-s" "ERROR_ON_UNDEFINED_SYMBOLS=1"
  = note: CRITICAL:root:Could not verify LLVM version: argument of type 'NoneType' is not iterable
          /home/jeehoonkang/.local/share/cargo-web/emscripten/x86_64-unknown-linux-gnu/emscripten-fastcomp/llc: error while loading shared libraries: libtinfo.so.5: cannot open shared object file: No such file or directory
          CRITICAL:root:fastcomp in use, but LLVM has not been built with the JavaScript backend as a target, llc reports:
          ===========================================================================
          (no targets could be identified: need more than 1 value to unpack)
          ===========================================================================
          CRITICAL:root:you can fall back to the older (pre-fastcomp) compiler core, although that is not recommended, see http://kripken.github.io/emscripten-site/docs/building_from_source/LLVM-Backend.html
          INFO:root:(Emscripten: Running sanity checks)
          CRITICAL:root:failing sanity checks due to previous fastcomp failure
          

error: aborting due to previous error

error: Could not compile `todomvc`.

To learn more, run the command again with --verbose.
error: build failed

Replace the `BTreeMap` in `Value::Object` with an opaque type

BTreeMap is a particular type of a map; we shouldn't expose details like that in our public interface.

We should have an opaque Object type instead of it, just as, for example, serde_json has. (See Value::Object and Map.)

  • Write a wrapper for BTreeMap called Object. It should be public just like other types we export (Value, Number, etc.). It should have a minimal interface consistent with what BTreeMap currently exposes.
  • Add necessary conversion impls:
    • impl From< Object > for Value (already done for BTreeMap; just has to be replaced)
    • impl TryFrom< Value > for Object (already done for BTreeMap; also has to be replaced)
    • impl From< BTreeMap > for Object
    • impl From< Object > for BTreeMap
    • impl From< HashMap > for Object
    • impl From< Object > for HashMap
  • Add tests for every conversion.

Expose DOM API

I looked through the documentation and failed to find any information on the subject.

Is it possible to expose DOM API, so that it can be compiled down to wasm and used inside Node.js instead of, for example, jsdom?

Related: mbasso/asm-dom#12, "wasm idea" inspired by wasm-brotli.

Thanks

`wasm32-unknown-unknown` support (ie: WebAssembly without Emscripten)

As you've probably heard, support for the native LLVM wasm target in rustc has landed. I understand that this doesn't do much yet, however I'd be interested to see if its possible to get a minimal version of stdweb working, without the emscripten API/runtime.

All the examples I can find (eg: https://www.hellorust.com/demos/) seem to be about using Rust code as a library (with a C FFI), and then driving it from Javascript. To go the other way around, it seems like you can import certain JS functions and call them from WebAssembly code (https://gist.github.com/cure53/f4581cee76d2445d8bd91f03d4fa7d3b). I doubt that alone would be enough to implement a js! macro like we have for emscripten, though.

Anyway, I guess I wanted to open this issue not because I expect anyone to immediately implement everything, but rather to start some discussion around the feature (as I believe the future of wasm probably doesn't involve emscripten), and to ask if you had any tips for how I could try to implement it myself.

Expand documentation on stdweb::event_loop()

You should call this before returning from main(), otherwise bad things will happen. is not sufficient documentation, because it raises the following questions:

  1. What if I include the code compiled into asm.js as part of a larger codebase and main() never gets called? Do I still have to call this, and when?

  2. What does this do, exactly? If I'm converting parts of a large JS codebase into Rust and I call this, what changes should I expect? (Also featuring: "What if I do not want Rust code to react to events? Do I still have to call it?", "I have not called it and have not observed any ill effects. What do?", etc.)

  3. How does calling this interact with -s NO_EXIT_RUNTIME=1 flag passed to emcc?

Looking at the implementation revealed nothing other than that it seems to be some kind of call required for any Emscripten code. If that is true, a link to emscripten documentation would solve point 2.

WebSocket support

I think that it'd be convenient to have WebSocket suported in stdweb in one or the other fashion, and working on some proof-of-concept code that mimicks (and could become an implementation of the interface of) the ws crate.

Where that should live depends on whether one sees stdweb as the place where all things DOM are being wrapped into the Rust world, or whether it's "std" enough that special-purpose libraries like ws will (on the wsm-unknown-unknown platoform) depend on it to implement their OS-specific backends.

Do you think that a wrapper around the browser's WebSocket should live in stdweb?

All requests to /js/app.js return ERR_ABORTED

screenshot from 2018-01-10 09-30-05

thread '<unnamed>' panicked at 'called `Option::unwrap()` on a `None` value', libcore/option.rs:335:21
stack backtrace:
   0:     0x5603f5c83c1b - std::sys::unix::backtrace::tracing::imp::unwind_backtrace::h9d1ecf383d3d35dd
                               at libstd/sys/unix/backtrace/tracing/gcc_s.rs:49
   1:     0x5603f5c90ee1 - std::sys_common::backtrace::print::h377b6336f9bd7acd
                               at libstd/sys_common/backtrace.rs:68
                               at libstd/sys_common/backtrace.rs:57
   2:     0x5603f5c7d770 - std::panicking::default_hook::{{closure}}::hd8ba10fcaf3b3605
                               at libstd/panicking.rs:381
   3:     0x5603f5c7d2ac - std::panicking::default_hook::hdadaf36afc2164e8
                               at libstd/panicking.rs:397
   4:     0x5603f5c7dbbb - std::panicking::rust_panic_with_hook::h856923614f259da2
                               at libstd/panicking.rs:577
   5:     0x5603f5c7da7e - std::panicking::begin_panic::he19efc0e8b16f633
                               at libstd/panicking.rs:538
   6:     0x5603f5c7d97a - std::panicking::begin_panic_fmt::hb84c3f6aa82e7f67
                               at libstd/panicking.rs:522
   7:     0x5603f5c7d912 - rust_begin_unwind
                               at libstd/panicking.rs:498
   8:     0x5603f5ce6390 - core::panicking::panic_fmt::h87b8697e64f0b225
                               at libcore/panicking.rs:71
   9:     0x5603f5ce62b6 - core::panicking::panic::h3b1a363ecbf0c21e
                               at libcore/panicking.rs:51
  10:     0x5603f59d452b - std::panicking::try::do_call::h8ce8770ad1f897e6
  11:     0x5603f5ca7f4e - __rust_maybe_catch_panic
                               at libpanic_unwind/lib.rs:102
  12:     0x5603f58d9ce5 - std::sys_common::backtrace::__rust_begin_short_backtrace::h3820d78ead11dfb3
  13:     0x5603f59d5ae5 - std::panicking::try::do_call::hc6a70fb34c59ed0c
  14:     0x5603f5ca7f4e - __rust_maybe_catch_panic
                               at libpanic_unwind/lib.rs:102
  15:     0x5603f598dc9a - <F as alloc::boxed::FnBox<A>>::call_box::h2ec1464b64f0c2e3
  16:     0x5603f5c8d247 - std::sys_common::thread::start_thread::hdbe346086586a07c
                               at /checkout/src/liballoc/boxed.rs:827
                               at libstd/sys_common/thread.rs:24
  17:     0x5603f5c7e228 - std::sys::unix::thread::Thread::new::thread_start::h780b8fb895b899ad
                               at libstd/sys/unix/thread.rs:90
  18:     0x7f9b23d67089 - start_thread
  19:     0x7f9b2388742e - __clone
  20:                0x0 - <unknown>
thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: "PoisonError { inner: .. }"', libcore/result.rs:916:5
stack backtrace:
   0:     0x5603f5c83c1b - std::sys::unix::backtrace::tracing::imp::unwind_backtrace::h9d1ecf383d3d35dd
                               at libstd/sys/unix/backtrace/tracing/gcc_s.rs:49
   1:     0x5603f5c90ee1 - std::sys_common::backtrace::print::h377b6336f9bd7acd
                               at libstd/sys_common/backtrace.rs:68
                               at libstd/sys_common/backtrace.rs:57
   2:     0x5603f5c7d770 - std::panicking::default_hook::{{closure}}::hd8ba10fcaf3b3605
                               at libstd/panicking.rs:381
   3:     0x5603f5c7d2ac - std::panicking::default_hook::hdadaf36afc2164e8
                               at libstd/panicking.rs:397
   4:     0x5603f5c7dbbb - std::panicking::rust_panic_with_hook::h856923614f259da2
                               at libstd/panicking.rs:577
   5:     0x5603f5c7da7e - std::panicking::begin_panic::he19efc0e8b16f633
                               at libstd/panicking.rs:538
   6:     0x5603f5c7d97a - std::panicking::begin_panic_fmt::hb84c3f6aa82e7f67
                               at libstd/panicking.rs:522
   7:     0x5603f5c7d912 - rust_begin_unwind
                               at libstd/panicking.rs:498
   8:     0x5603f5ce6390 - core::panicking::panic_fmt::h87b8697e64f0b225
                               at libcore/panicking.rs:71
   9:     0x5603f5905abe - core::result::unwrap_failed::h1ad62b5dc4b86e2e
  10:     0x5603f59d4f3b - std::panicking::try::do_call::h8ce8770ad1f897e6
  11:     0x5603f5ca7f4e - __rust_maybe_catch_panic
                               at libpanic_unwind/lib.rs:102
  12:     0x5603f58d9ce5 - std::sys_common::backtrace::__rust_begin_short_backtrace::h3820d78ead11dfb3
  13:     0x5603f59d5ae5 - std::panicking::try::do_call::hc6a70fb34c59ed0c
  14:     0x5603f5ca7f4e - __rust_maybe_catch_panic
                               at libpanic_unwind/lib.rs:102
  15:     0x5603f598dc9a - <F as alloc::boxed::FnBox<A>>::call_box::h2ec1464b64f0c2e3
  16:     0x5603f5c8d247 - std::sys_common::thread::start_thread::hdbe346086586a07c
                               at /checkout/src/liballoc/boxed.rs:827
                               at libstd/sys_common/thread.rs:24
  17:     0x5603f5c7e228 - std::sys::unix::thread::Thread::new::thread_start::h780b8fb895b899ad
                               at libstd/sys/unix/thread.rs:90
  18:     0x7f9b23d67089 - start_thread
  19:     0x7f9b2388742e - __clone
  20:                0x0 - <unknown>

This is just running an unmodified version of the TodoMVC example, using the latest versions of cargo-web and stdweb.

Write a procedural macro to replace the `js!` macro on nightly (without parsing the JavaScript)

The js! macro is truly a thing of terror, however we don't have much choice if we want to work on stable.

That said, it would we worthwhile to convert it to a nightly-only procedural macro to prepare for the future where procedural macros will be stabilized.

This will also help with the compile times, which are negatively impacted by the way the current js! macro is implemented.

  • Write a nightly-only js! procedural macro.
  • Add nightly optional feature to Cargo.toml and use the procedural js! only when that feature is switched on.

Feature request: imlement trait `TryFrom<usize>` for `stdweb::Value`

Just what it says on the tin. It's weird that TryFrom<u64> is implemented for stdweb::Value but TryFrom<usize> is not.

Use case: I was trying to pass two arrays of integers into JS, iterate over them to do some lookup based on both and call functions with side effects on the result of lookup. I came up with the following code:

    let array_a: stdweb::Value = vec_a.into();
    let array_b: stdweb::Value = vec_b.into();
    js! {
        var lookup_result = [];
        var length = @{array_a}.length;
        for (var i = 0; i < ; i++) {
            lookup_result.push(lookup_a(@{array_a}[i]).lookup_b(@{array_b}[i]));
        }
        func_with_side_effects(lookup_result)
    };

But Rust complained that array_a is moved at length lookup and I cannot use it again. So I've tried adding length and passing it to JS explicitly:

let length: stdweb::Value = position_hashes.len().try_into().unwrap();

but that complained that "the trait stdweb::unstable::TryFrom<usize> is not implemented for stdweb::Value"

Setting callback for async functions

I'm trying to use fetch to load a file and then call a closure on the Rust side, like this:

let call_fn = |txt: String| {
    println!( "{}", txt );
};

js! {
    var call_fn = @{call_fn};
    fetch( "/test.csv" ).then((res) => res.text()).then(call_fn);
}

But I'm getting this error:

Panic error message: cannot access stdout during shutdown

Any chance to make it work?

serde_json usage within stdweb?

(Creating a separate issue here; the PR already has enough going on)

Background: I noticed the src/ecosystem mods there, with serde and serde_json already present. Great idea btw!

I'm particularly curious about ecosystem/serde_json. It doesn't look like it's really used anywhere, but it has a critical TryFrom implementation. Question 0: as it stands, does this work? (Looks good to me...)

If it does, then here's the situation: say I have a block of serde JSON, e.g.

let s =  r#"{"greeting_string": "hello"}"#;
let json_object: Value = serde_json::from_str(s)?; <-- serde_json Value, not stdweb Value...
// pretty cool that this works, without strong typing
println!(json_object["greeting_string"]); // hello

Nothing new here.

Say we want to do something with it in stdweb, e.g.

use serde_json::value::Value as JsonValue;
use webcore::value::Value;

fn say_hello_to_world(json_value: &JsonValue) {
    // assuming a json_value object has a key and value for "greeting_string" and so on
    js!( @(no_return)
        console.log(@{json_value["greeting_string"]} + " world!");
    );
}

This example will break, since a serde JsonValue can't be marshaled into a JS object without that ecosystem tie-in (or a similar tie-in or implementation). How can that be done?

I've tried some stuff on my own and it blew up in my face...

As for now, this could be a documentation question, unless there is more involved in integrating with stdweb. Either way, I can see about documenting it in the README

Thanks!

Issue when calling Rust from JS

Platform: OSX 10.12.6
Compiler: rustc 1.22.0-nightly (150b625a0 2017-10-08)

I have the following code:

extern crate stdweb;
use stdweb::Value;
use stdweb::unstable::TryFrom;

#[no_mangle]
pub extern fn print_value(v: Value) {
    println!("{:?}", &v);
    println!("{:?}", String::try_from(v));
}

fn main() {
    stdweb::initialize();
    stdweb::event_loop();
}

The code appears to compile just fine, but calling _print_value from JS leads to strange results:

_print_value(123)
> String("\u{0}\u{0}\u{0}\u{1}")
> Ok("\u{0}\u{0}\u{0}\u{1}")

_print_value("Hello")
> Maximum call stack size exceeded

The results I expected:

_print_value(123)
> Number(123)
> Err(...)

_print_value("Hello")
> String("Hello")
> Ok("Hello")

Have I been using Value incorrectly or is there a bug during translation from JS values to Value?

JsSerializable doesn't handle Value::Reference correctly

There seems to be a bug when passing structs containing a Value::Reference to JavaScript. When accessing the struct field containing the reference in JavaScript it only contains an empty object instead of the reference passed in by Rust.

See the below code for clarification.

#[derive(Serialize)]
struct ReferenceHolder {
    reference: Value
}
js_serializable!(ReferenceHolder);

fn test_ref() {
    let message = "Hello!".as_bytes();
    let reference = Value::Reference(Reference::from(TypedArray::from(message)));
    let obj = ReferenceHolder {
        reference: Value::Reference(Reference::from(TypedArray::from(message)))
    };

    js! {
        console.log(@{reference});
        // Prints `Uint8Array [ 72, 101, 108, 108, 111, 33 ]`

        console.log(@{obj});
        // Prints `Object { reference: {} }`
    };
}

fn main() {
    stdweb::initialize();

    test_ref();
}

Establish a pattern for JS exception handling

Lots of web APIs throw exceptions, so we should establish a pattern for passing these exceptions back to Rust in a nice way.

For example, Node::remove_child uses a pattern of returning a bool when an exception happens, which is then converted into a Rust NotFoundErr as appropriate.

I could picture this pattern being wrapped into some kind of js_try! macro. Could the exception itself be serialized to Rust if we implemented the JS Error type? That way, instead of a bool, the JS could return the value itself or the exception, which could be converted into the proper Rust type.

What should the Rust error type be? For example, Node.removeChild can return other exception types. Should we make a more global webapi::Error enum that represents every possible exception that JS can throw?

Can not use js_serializable! from outside the create

When I try to use js_serializable! I get the following error:

error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
  --> src/lib.rs:45:1
   |
45 | js_serializable!(MyType);
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
   |
   = note: the impl does not reference any types defined in this crate
   = note: define and implement a trait or new type instead
   = note: this error originates in a macro outside of the current crate

The line is right below the type that I have defined so it should work. I don't know if there's something I can do to get a more precise error message as the macro expands quite a bit it's hare (at least for me) to pinpoint the error.

A bit OT, but I don't know where else to ask. Is it possible to pass values to JS without serializing them?

More DOM methods

Looking through the documentation, pretty common methods like setAttribute or getAttribute are notably absent. Are these things that are on the radar, or how easy is it to implement this now as an end-user (I'm assuming using some form of the js! macro?)

Road to `0.4.0`

  • (breaking change) Get rid of every usize from src/webapi.
  • (breaking change) Rename KeydownEvent into KeyDownEvent, KeyupEvent into KeyUpEvent and Keypress into KeyPressEvent to be consistent with the mouse events.
  • (breaking change) Go through all of our bindings, see which ones can fail in the specs, and add appropriate Result<_, _> return types.
  • (breaking change) Rename every ReadyState to something unique.
  • (breaking change) Support declarative exports using a procedural macro instead of assigning to Module.exports on wasm32-unknown-unknown`.
  • Add a link to the actual specs for everything we have bindings for.
  • Split event.rs into multiple files (#58)
  • Merge DOMException (#89)
  • Get rid of xml_http_request namespace.
  • Add a proper changelog to README.
  • Make sure every example works.
  • Update the examples in the README.

In general I'd like to minimize the amount of breaking changes we do, so it'd be nice to get as many of them out of the way as soon as possible, especially the cleanup-y ones.

Compiling in release mode fails

I'm trying to run the todo example.

$ cargo web start --port 8008 --release
error: linking with `emcc` failed: exit code: 1
  |
  = note: "emcc" "-s" "DISABLE_EXCEPTION_CATCHING=0" "-L" "/home/arne/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/asmjs-unknown-emscripten/lib" "/tmp/stdweb/examples/todomvc/target/asmjs-unknown-emscripten/release/deps/todomvc-6fb1feda799b1a50.0.o" "-o" "/tmp/stdweb/examples/todomvc/target/asmjs-unknown-emscripten/release/deps/todomvc-6fb1feda799b1a50.js" "-s" "EXPORTED_FUNCTIONS=[\"_main\",\"_rust_eh_personality\"]" "-O3" "--memory-init-file" "0" "-g0" "-s" "DEFAULT_LIBRARY_FUNCS_TO_INCLUDE=[]" "-L" "/tmp/stdweb/examples/todomvc/target/asmjs-unknown-emscripten/release/deps" "-L" "/tmp/stdweb/examples/todomvc/target/release/deps" "-L" "/home/arne/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/asmjs-unknown-emscripten/lib" "/tmp/stdweb/examples/todomvc/target/asmjs-unknown-emscripten/release/deps/libstdweb-f006930ac2288929.rlib" "/tmp/stdweb/examples/todomvc/target/asmjs-unknown-emscripten/release/deps/libserde_json-f08a34ce468f736d.rlib" "/tmp/stdweb/examples/todomvc/target/asmjs-unknown-emscripten/release/deps/libdtoa-8272a2cba0c82a0d.rlib" "/tmp/stdweb/examples/todomvc/target/asmjs-unknown-emscripten/release/deps/libnum_traits-d94c71f49a0f03a7.rlib" "/tmp/stdweb/examples/todomvc/target/asmjs-unknown-emscripten/release/deps/libserde-16cc3e2e813f4b59.rlib" "/tmp/stdweb/examples/todomvc/target/asmjs-unknown-emscripten/release/deps/libitoa-99898550fe0c9aaa.rlib" "/home/arne/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/asmjs-unknown-emscripten/lib/libstd-35ad9950c7e5074b.rlib" "/home/arne/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/asmjs-unknown-emscripten/lib/libpanic_unwind-fb44afc024bbc636.rlib" "/home/arne/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/asmjs-unknown-emscripten/lib/libunwind-14b8f3202acdad6a.rlib" "/home/arne/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/asmjs-unknown-emscripten/lib/librand-20a50a22d4c2b1e9.rlib" "/home/arne/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/asmjs-unknown-emscripten/lib/libcollections-b479831207997444.rlib" "/home/arne/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/asmjs-unknown-emscripten/lib/liballoc-10b591f1a68dd370.rlib" "/home/arne/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/asmjs-unknown-emscripten/lib/libstd_unicode-f4f0ae88f5ad8ad4.rlib" "/home/arne/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/asmjs-unknown-emscripten/lib/liballoc_system-06d737faf6076d7c.rlib" "/home/arne/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/asmjs-unknown-emscripten/lib/liblibc-6ecacccb5bdc4911.rlib" "/home/arne/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/asmjs-unknown-emscripten/lib/libcore-bfaa82017ca17cb2.rlib" "/home/arne/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/asmjs-unknown-emscripten/lib/libcompiler_builtins-863b57a66ba6c3e1.rlib" "-l" "c" "-s" "ERROR_ON_UNDEFINED_SYMBOLS=1"
  = note: WARNING:root:(Emscripten: system change: 1.37.10|/home/arne/bin/clang/e1.37.13_64bit|4.0 vs 1.37.13|/home/arne/bin/clang/e1.37.13_64bit|4.0, clearing cache)
          ERROR:root:Emscripten, llvm and clang repo versions do not match, this is dangerous (1.37.10, 1.37.13, 1.37.13)
          ERROR:root:Make sure to use the same branch in each repo, and to be up-to-date on each. See http://kripken.github.io/emscripten-site/docs/building_from_source/LLVM-Backend.html
          INFO:root:(Emscripten: Running sanity checks)
          INFO:root:generating system library: libc.bc... (this will be cached in "/home/arne/.emscripten_cache/asmjs/libc.bc" for subsequent builds)
          INFO:root: - ok
          INFO:root:generating system library: dlmalloc.bc... (this will be cached in "/home/arne/.emscripten_cache/asmjs/dlmalloc.bc" for subsequent builds)
          INFO:root: - ok
          
          /home/arne/.local/share/cargo-web/emscripten/x86_64-unknown-linux-gnu/emscripten/tools/eliminator/node_modules/uglify-js/lib/parse-js.js:272
                  throw new JS_Parse_Error(message, line, col, pos);
                  ^
          TypeError: (intermediate value) is not a function
              at new JS_Parse_Error (/home/arne/.local/share/cargo-web/emscripten/x86_64-unknown-linux-gnu/emscripten/tools/eliminator/node_modules/uglify-js/lib/parse-js.js:261:21)
              at js_error (/home/arne/.local/share/cargo-web/emscripten/x86_64-unknown-linux-gnu/emscripten/tools/eliminator/node_modules/uglify-js/lib/parse-js.js:272:15)
              at croak (/home/arne/.local/share/cargo-web/emscripten/x86_64-unknown-linux-gnu/emscripten/tools/eliminator/node_modules/uglify-js/lib/parse-js.js:742:17)
              at token_error (/home/arne/.local/share/cargo-web/emscripten/x86_64-unknown-linux-gnu/emscripten/tools/eliminator/node_modules/uglify-js/lib/parse-js.js:749:17)
              at unexpected (/home/arne/.local/share/cargo-web/emscripten/x86_64-unknown-linux-gnu/emscripten/tools/eliminator/node_modules/uglify-js/lib/parse-js.js:755:17)
              at Object.semicolon (/home/arne/.local/share/cargo-web/emscripten/x86_64-unknown-linux-gnu/emscripten/tools/eliminator/node_modules/uglify-js/lib/parse-js.js:775:51)
              at prog1 (/home/arne/.local/share/cargo-web/emscripten/x86_64-unknown-linux-gnu/emscripten/tools/eliminator/node_modules/uglify-js/lib/parse-js.js:1314:29)
              at simple_statement (/home/arne/.local/share/cargo-web/emscripten/x86_64-unknown-linux-gnu/emscripten/tools/eliminator/node_modules/uglify-js/lib/parse-js.js:906:35)
              at /home/arne/.local/share/cargo-web/emscripten/x86_64-unknown-linux-gnu/emscripten/tools/eliminator/node_modules/uglify-js/lib/parse-js.js:816:35
              at block_ (/home/arne/.local/share/cargo-web/emscripten/x86_64-unknown-linux-gnu/emscripten/tools/eliminator/node_modules/uglify-js/lib/parse-js.js:999:32)
              at /home/arne/.local/share/cargo-web/emscripten/x86_64-unknown-linux-gnu/emscripten/tools/eliminator/node_modules/uglify-js/lib/parse-js.js:821:52
          Traceback (most recent call last):
            File "/home/arne/.local/share/cargo-web/emscripten/x86_64-unknown-linux-gnu/emscripten/emcc", line 13, in <module>
              emcc.run()
            File "/home/arne/.local/share/cargo-web/emscripten/x86_64-unknown-linux-gnu/emscripten/emcc.py", line 1982, in run
              JSOptimizer.flush()
            File "/home/arne/.local/share/cargo-web/emscripten/x86_64-unknown-linux-gnu/emscripten/emcc.py", line 1877, in flush
              run_passes(chunks[0], title, just_split=False, just_concat=False)
            File "/home/arne/.local/share/cargo-web/emscripten/x86_64-unknown-linux-gnu/emscripten/emcc.py", line 1850, in run_passes
              final = shared.Building.js_optimizer(final, passes, debug_level >= 4, JSOptimizer.extra_info, just_split=just_split, just_concat=just_concat)
            File "/home/arne/.local/share/cargo-web/emscripten/x86_64-unknown-linux-gnu/emscripten/tools/shared.py", line 2046, in js_optimizer
              ret = js_optimizer.run(filename, passes, NODE_JS, debug, extra_info, just_split, just_concat)
            File "/home/arne/.local/share/cargo-web/emscripten/x86_64-unknown-linux-gnu/emscripten/tools/js_optimizer.py", line 563, in run
              return temp_files.run_and_clean(lambda: run_on_js(filename, passes, js_engine, source_map, extra_info, just_split, just_concat))
            File "/home/arne/.local/share/cargo-web/emscripten/x86_64-unknown-linux-gnu/emscripten/tools/tempfiles.py", line 78, in run_and_clean
              return func()
            File "/home/arne/.local/share/cargo-web/emscripten/x86_64-unknown-linux-gnu/emscripten/tools/js_optimizer.py", line 563, in <lambda>
              return temp_files.run_and_clean(lambda: run_on_js(filename, passes, js_engine, source_map, extra_info, just_split, just_concat))
            File "/home/arne/.local/share/cargo-web/emscripten/x86_64-unknown-linux-gnu/emscripten/tools/js_optimizer.py", line 502, in run_on_js
              assert proc.returncode == 0
          AssertionError
          

error: aborting due to previous error(s)

error: Could not compile `todomvc`.

To learn more, run the command again with --verbose.
error: build failed

Shouldn't Window::set_timeout require F: 'static?

I'm not very familiar with the way the library works, but to me the callback passed to set_timeout should be 'static. Otherwise it could borrow a local variable and reference it after it's been destroyed.

Custom event handlers?

I'm trying to watch window resize events but ResizeEvent isn't implemented in the stdweb::events module.

I attempted to define and implement it myself but I'm missing a bunch of reference boilerplate which is handled by the reference_boilerplate macro (not re-exported).

What's the recommended way to handle undefined events?

Thanks!


I'm using the js!{} macro for now:

js!{
    Module.exports.myfunc = @{myfunc};
    window.addEventListener("resize", function(e) { Module.exports.myfunc() });
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.