Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

js-sys: Expose bindings to ALL the global JS things #275

Closed
fitzgen opened this issue Jun 18, 2018 · 152 comments
Closed

js-sys: Expose bindings to ALL the global JS things #275

fitzgen opened this issue Jun 18, 2018 · 152 comments
Labels
good first issue This is a good issue for people who have never contributed to wasm-bindgen before help wanted We could use some help fixing this issue! js-sys Issues related to the `js-sys` crate more-types Adding support for more Rust types to cross the boundary

Comments

@fitzgen
Copy link
Member

fitzgen commented Jun 18, 2018

This is about exposing ALL of the globally available JS APIs through the js-sys crate. Things that are guaranteed by the ECMAScript standard, not Web/Node/etc APIs.

A good overview/list/documentation of these APIs is available here and I've also made a checklist below. As we implement bindings for these APIs, I will check them off.

How to Implement New Bindings

  • Comment here saying which thing you are going to make bindings for (so that we don't accidentally duplicate effort). I'll add your username next to the checkbox item.

  • Open the MDN page for the relevant JS API.

  • Open crates/js-sys/src/lib.rs in your editor; this is the file where we are implementing the bindings.

  • Follow the instructions in crates/js-sys/src/lib.rs about how to add new bindings:

    // When adding new imports:
    //
    // * Keep imports in alphabetical order.
    //
    // * Rename imports with `js_name = ...` according to the note about `camelCase`
    // and `snake_case` in the module's documentation above.
    //
    // * Include the one sentence summary of the import from the MDN link in the
    // module's documentation above, and the MDN link itself.
    //
    // * If a function or method can throw an exception, make it catchable by adding
    // `#[wasm_bindgen(catch)]`.
    //
    // * Add a new `#[test]` into the appropriate file in the
    // `tests/all/js_globals/` directory. If the imported function or
    // method can throw an exception, make sure to also add test coverage
    // for that case.

  • Add a test for the new binding to crates/js-sys/tests/wasm/MyType.rs

  • Run the JS global API bindings tests with cargo test -p js-sys --target wasm32-unknown-unknown

  • Send a pull request! 😸


Depends on this PR for the initial skeleton and infrastructure:


All String bindings depend on:


  • Array

    • Array.length (@robertDurst)

    • Array.from()

    • Array.isArray()

    • Array.of()

    • Array.prototype.concat()

    • Array.prototype.copyWithin()

    • Array.prototype.entries()

    • Array.prototype.every()

    • Array.prototype.fill()

    • Array.prototype.filter()

    • Array.prototype.find()

    • Array.prototype.findIndex()

    • Array.prototype.forEach()

    • Array.prototype.includes()

    • Array.prototype.indexOf()

    • Array.prototype.join()

    • Array.prototype.keys()

    • Array.prototype.lastIndexOf()

    • Array.prototype.map()

    • Array.prototype.pop() (@sepiropht)

    • Array.prototype.push()

    • Array.prototype.reduce()

    • Array.prototype.reduceRight()

    • Array.prototype.reverse()

    • Array.prototype.shift()

    • Array.prototype.slice()

    • Array.prototype.some()

    • Array.prototype.sort()

    • Array.prototype.splice()

    • Array.prototype.toLocaleString()

    • Array.prototype.toString()

    • Array.prototype.unshift()

    • Array.prototype.values()

  • ArrayBuffer

    • ArrayBuffer.prototype.byteLength

    • ArrayBuffer.isView()

    • ArrayBuffer.prototype.slice()

  • Boolean

  • DataView

    • DataView.prototype.buffer

    • DataView.prototype.byteLength

    • DataView.prototype.byteOffset

    • DataView.prototype.getFloat32()

    • DataView.prototype.getFloat64()

    • DataView.prototype.getInt16()

    • DataView.prototype.getInt32()

    • DataView.prototype.getInt8()

    • DataView.prototype.getUint16()

    • DataView.prototype.getUint32()

    • DataView.prototype.getUint8()

    • DataView.prototype.setFloat32()

    • DataView.prototype.setFloat64()

    • DataView.prototype.setInt16()

    • DataView.prototype.setInt32()

    • DataView.prototype.setInt8()

    • DataView.prototype.setUint16()

    • DataView.prototype.setUint32()

    • DataView.prototype.setUint8()

  • Date

    • Date.UTC()

    • Date.now()

    • Date.parse()

    • Date.prototype.getDate()

    • Date.prototype.getDay()

    • Date.prototype.getFullYear()

    • Date.prototype.getHours()

    • Date.prototype.getMilliseconds()

    • Date.prototype.getMinutes()

    • Date.prototype.getMonth()

    • Date.prototype.getSeconds()

    • Date.prototype.getTime()

    • Date.prototype.getTimezoneOffset()

    • Date.prototype.getUTCDate()

    • Date.prototype.getUTCDay()

    • Date.prototype.getUTCFullYear()

    • Date.prototype.getUTCHours()

    • Date.prototype.getUTCMilliseconds()

    • Date.prototype.getUTCMinutes()

    • Date.prototype.getUTCMonth()

    • Date.prototype.getUTCSeconds()

    • Date.prototype.setDate()

    • Date.prototype.setFullYear()

    • Date.prototype.setHours()

    • Date.prototype.setMilliseconds()

    • Date.prototype.setMinutes()

    • Date.prototype.setMonth()

    • Date.prototype.setSeconds()

    • Date.prototype.setTime()

    • Date.prototype.setUTCDate()

    • Date.prototype.setUTCFullYear()

    • Date.prototype.setUTCHours()

    • Date.prototype.setUTCMilliseconds()

    • Date.prototype.setUTCMinutes()

    • Date.prototype.setUTCMonth()

    • Date.prototype.setUTCSeconds()

    • Date.prototype.toDateString()

    • Date.prototype.toISOString()

    • Date.prototype.toJSON()

    • Date.prototype.toLocaleDateString()

    • Date.prototype.toLocaleString()

    • Date.prototype.toLocaleTimeString()

    • Date.prototype.toString()

    • Date.prototype.toTimeString()

    • Date.prototype.toUTCString()

    • Date.prototype.valueOf()

  • Error

    • Error.prototype.message

    • Error.prototype.name

    • Error.prototype.toString()

  • EvalError

  • Float32Array

  • Float64Array

  • Function

    • Function.length

    • Function.name

    • Function.prototype.apply()

    • Function.prototype.bind()

    • Function.prototype.call()

    • Function.prototype.toString()

  • Generator

    • Generator.prototype.next()

    • Generator.prototype.return()

    • Generator.prototype.throw()

  • Int16Array

  • Int32Array

  • Int8Array

  • Intl

    • Intl.getCanonicalLocales()
  • Intl.Collator

    • Intl.Collator.prototype.compare

    • Intl.Collator.prototype.resolvedOptions()

    • Intl.Collator.supportedLocalesOf()

  • Intl.DateTimeFormat

    • Intl.DateTimeFormat.prototype.format

    • Intl.DateTimeFormat.prototype.formatToParts()

    • Intl.DateTimeFormat.prototype.resolvedOptions()

    • Intl.DateTimeFormat.supportedLocalesOf()

  • Intl.NumberFormat

    • Intl.NumberFormat.prototype.format

    • Intl.NumberFormat.prototype.formatToParts()

    • Intl.NumberFormat.prototype.resolvedOptions()

    • Intl.NumberFormat.supportedLocalesOf()

  • Intl.PluralRules

    • Intl.PluralRules.prototype.resolvedOptions()

    • Intl.PluralRules.select()

    • Intl.PluralRules.supportedLocalesOf()

  • JSON

    • JSON.parse()

    • JSON.stringify()

  • Map

    • Map.prototype.size

    • Map.prototype.clear()

    • Map.prototype.delete()

    • Map.prototype.entries()

    • Map.prototype.forEach()

    • Map.prototype.get()

    • Map.prototype.has()

    • Map.prototype.keys()

    • Map.prototype.set()

    • Map.prototype.values()

  • Math

    • Math.abs()

    • Math.acos()

    • Math.acosh()

    • Math.asin()

    • Math.asinh()

    • Math.atan()

    • Math.atan2()

    • Math.atanh()

    • Math.cbrt()

    • Math.ceil()

    • Math.clz32()

    • Math.cos()

    • Math.cosh()

    • Math.exp()

    • Math.expm1()

    • Math.floor()

    • Math.fround()

    • Math.hypot()

    • Math.imul()

    • Math.log()

    • Math.log10()

    • Math.log1p()

    • Math.log2()

    • Math.max()

    • Math.min()

    • Math.pow()

    • Math.random()

    • Math.round()

    • Math.sign()

    • Math.sin()

    • Math.sinh()

    • Math.sqrt()

    • Math.tan()

    • Math.tanh()

    • Math.trunc()

  • Number

    • Number.isFinite()

    • Number.isInteger()

    • Number.isNaN()

    • Number.isSafeInteger()

    • Number.parseFloat()

    • Number.parseInt()

    • Number.prototype.toExponential()

    • Number.prototype.toFixed()

    • Number.prototype.toLocaleString()

    • Number.prototype.toPrecision()

    • Number.prototype.toString()

    • Number.prototype.valueOf()

  • Object

    • Object.prototype.constructor

    • Object.assign()

    • Object.create()

    • Object.defineProperties()

    • Object.defineProperty()

    • Object.entries()

    • Object.freeze()

    • Object.getOwnPropertyDescriptor()

    • Object.getOwnPropertyDescriptors()

    • Object.getOwnPropertyNames()

    • Object.getOwnPropertySymbols()

    • Object.getPrototypeOf()

    • Object.is()

    • Object.isExtensible()

    • Object.isFrozen()

    • Object.isSealed()

    • Object.keys()

    • Object.preventExtensions()

    • Object.prototype.hasOwnProperty()

    • Object.prototype.isPrototypeOf() (@belfz)

    • Object.prototype.propertyIsEnumerable() (@belfz )

    • Object.prototype.toLocaleString()

    • Object.prototype.toString() (@jonathan-s)

    • Object.prototype.valueOf()

    • Object.seal()

    • Object.setPrototypeOf()

    • Object.values()

  • Promise

    • Promise.all()

    • Promise.prototype.catch()

    • Promise.prototype.finally()

    • Promise.prototype.then()

    • Promise.race()

    • Promise.reject()

    • Promise.resolve()

  • Proxy

  • RangeError

  • ReferenceError

  • Reflect

    • Reflect.apply()

    • Reflect.construct()

    • Reflect.defineProperty()

    • Reflect.deleteProperty()

    • Reflect.get()

    • Reflect.getOwnPropertyDescriptor()

    • Reflect.getPrototypeOf()

    • Reflect.has()

    • Reflect.isExtensible()

    • Reflect.ownKeys()

    • Reflect.preventExtensions()

    • Reflect.set()

    • Reflect.setPrototypeOf()

  • RegExp

    • RegExp.$1-$9

    • RegExp.input ($_)

    • RegExp.lastMatch ($&)

    • RegExp.lastParen ($+)

    • RegExp.leftContext ($)`

    • RegExp.prototype.flags

    • RegExp.prototype.global

    • RegExp.prototype.ignoreCase

    • RegExp.prototype.multiline

    • RegExp.prototype.source

    • RegExp.prototype.sticky

    • RegExp.prototype.unicode

    • RegExp.rightContext ($')

    • regexp.lastIndex

    • RegExp.prototype.exec()

    • RegExp.prototype.test()

    • RegExp.prototype.toString()

  • Set

    • Set.prototype.size

    • Set.prototype.add()

    • Set.prototype.clear()

    • Set.prototype.delete()

    • Set.prototype.entries()

    • Set.prototype.forEach()

    • Set.prototype.has()

    • Set.prototype.values()

  • String

    • string.length

    • String.fromCharCode()

    • String.fromCodePoint()

    • String.prototype.charAt()

    • String.prototype.charCodeAt()

    • String.prototype.codePointAt()

    • String.prototype.concat()

    • String.prototype.endsWith()

    • String.prototype.includes()

    • String.prototype.indexOf()

    • String.prototype.lastIndexOf()

    • String.prototype.localeCompare()

    • String.prototype.match()

    • String.prototype.normalize()

    • String.prototype.padEnd()

    • String.prototype.padStart()

    • String.prototype.repeat()

    • String.prototype.replace()

    • String.prototype.search()

    • String.prototype.slice()

    • String.prototype.split()

    • String.prototype.startsWith()

    • String.prototype.substr()

    • String.prototype.substring()

    • String.prototype.toLocaleLowerCase()

    • String.prototype.toLocaleUpperCase()

    • String.prototype.toLowerCase()

    • String.prototype.toString()

    • String.prototype.toUpperCase()

    • String.prototype.trim()

    • String.prototype.trimEnd()

    • String.prototype.trimStart()

    • String.prototype.valueOf()

    • String.raw()

  • Symbol

    • Symbol.hasInstance

    • Symbol.isConcatSpreadable

    • Symbol.iterator

    • Symbol.match

    • Symbol.replace

    • Symbol.search

    • Symbol.species

    • Symbol.split

    • Symbol.toPrimitive

    • Symbol.toStringTag

    • Symbol.unscopables

    • Symbol.for()

    • Symbol.keyFor()

    • Symbol.prototype.toString()

    • Symbol.prototype.valueOf()

  • SyntaxError

  • TypeError

  • URIError

  • Uint16Array

  • Uint32Array

  • Uint8Array

  • Uint8ClampedArray

  • WeakMap

    • WeakMap.prototype.delete()

    • WeakMap.prototype.get()

    • WeakMap.prototype.has()

    • WeakMap.prototype.set()

  • WeakSet

    • WeakSet.prototype.add()

    • WeakSet.prototype.delete()

    • WeakSet.prototype.has()

  • WebAssembly

    • WebAssembly.compile()

    • WebAssembly.instantiate()

    • WebAssembly.instantiateStreaming()

    • WebAssembly.validate()

  • WebAssembly.Module

    • WebAssembly.Module.customSections()

    • WebAssembly.Module.exports()

    • WebAssembly.Module.imports()

  • WebAssembly.Instance

    • WebAssembly.Instance.prototype.exports
  • WebAssembly.Memory

    • WebAssembly.Memory.prototype.buffer

    • WebAssembly.Memory.prototype.grow

  • WebAssembly.Table

    • WebAssembly.Table.prototype.length

    • WebAssembly.Table.prototype.get

    • WebAssembly.Table.prototype.grow

    • WebAssembly.Table.prototype.set

  • WebAssembly.CompileError

  • WebAssembly.LinkError

  • WebAssembly.RuntimeError

  • decodeURI()

  • decodeURIComponent()

  • encodeURI()

  • encodeURIComponent()

  • escape()

  • eval()

  • isFinite()

  • isNaN()

  • null

  • parseFloat()

  • parseInt()

  • undefined

  • unescape()

@fitzgen fitzgen added help wanted We could use some help fixing this issue! good first issue This is a good issue for people who have never contributed to wasm-bindgen before more-types Adding support for more Rust types to cross the boundary labels Jun 18, 2018
@fitzgen fitzgen changed the title Expose bindings to all the global JS things Expose bindings to ALL the global JS things Jun 18, 2018
@coreh
Copy link

coreh commented Jun 19, 2018

Would it make sense to reference (or perhaps even automatically convert?) the TypeScript definitions for these? Additional definitions are separated per ES version and available on this directory.

@fitzgen
Copy link
Member Author

fitzgen commented Jun 19, 2018

@coreh we are building a TypeScript frontend to wasm-bindgen (cc @spastorino) but it has a bit of a ways to go before we can rely on it. Additionally, .d.ts files don't give us information about whether a method can throw or not, so we would have to be conservative and assume that they always do, which isn't great to have at the most foundational layer of bindings.

For Web APIs, we intend to use our work-in-progress WebIDL frontend to generate a sys crate for the whole Web platform. WebIDL does give us more info, and crucially whether a method throws or not.

@sepiropht
Copy link
Contributor

sepiropht commented Jun 19, 2018

I would like to help! I know some Javascript and i' m currently learning rust. But i want to understand, maybe my question is silly. What is the purpose of all this bindings ?

@wismer
Copy link
Contributor

wismer commented Jun 19, 2018

How would multiple, optional arguments be handled for something like Array.prototype.concat? And on the subject of Array, would the type for this be Array<JsValue> ?

@fitzgen
Copy link
Member Author

fitzgen commented Jun 19, 2018

@sepiropht the purpose is so that we don't duplicate bindings across the ecosystem (or even within a single crate dependency graph) and people can be productive more quickly.

@fitzgen
Copy link
Member Author

fitzgen commented Jun 19, 2018

@wismer we don't have great support for optional arguments at the moment, so for now it is best to do one of:

  • write bindings for a different function/object
  • ignore the optional bindings
  • always require the optional bindings

different choices may make sense for different methods.

@sepiropht
Copy link
Contributor

sepiropht commented Jun 19, 2018

Thanks @fitzgen and @fitzgen for the quick response. But this is still too advanced for me. Maybe i should start first by reading how wasm-bingen works.

@fitzgen
Copy link
Member Author

fitzgen commented Jun 19, 2018

@wismer

And on the subject of Array, would the type for this be Array ?

wasm-bindgen doesn't support generics right now (supporting generics across an ABI boundary without a JIT compiler to dynamically compile monomorphizations of generic instantiations is hard) so we would only support JsValue. It would be possible to build newtypes with phantoms on top of that that only let Rust code put in instances of the expected type, and then there would have to also be dynamic checks for the JS side of things somehow.

@wismer
Copy link
Contributor

wismer commented Jun 19, 2018

@fitzgen ok thanks - I'm eager to get started but I've run into a hiccup with the tests and it looks like it's a propagating JS error regarding WebAssembly is not defined - I've tried npm install and the link to the contributing guidelines is broken https://rustwasm.github.io/wasm-bindgen/contributing.html, so I'm not sure what build step I may be missing.

@fitzgen
Copy link
Member Author

fitzgen commented Jun 19, 2018

@wismer yeah, I'm trying to fix the gh-pages deploy on travis ci right now >.<

Make sure you've got node 10 installed (there are tests that depend on BigInt, which is >= 10; WebAssembly is >= 8).

@fitzgen
Copy link
Member Author

fitzgen commented Jun 19, 2018

Also, the gh-pages should be fixed now!

@wismer
Copy link
Contributor

wismer commented Jun 20, 2018

@fitzgen is this close to what you are looking for? (Array.prototype.indexOf)

extern {
    pub type Array;

    #[wasm_bindgen(method, js_name = indexOf)]
    pub fn index_of(this: &Array, value: JsValue) -> i32;
}
// Array.rs
#[test]
fn index_of() {
    project()
        .file("src/lib.rs", r#"
            #![feature(proc_macro, wasm_custom_section)]

            extern crate wasm_bindgen;
            use wasm_bindgen::prelude::*;
            use wasm_bindgen::js;

            #[wasm_bindgen]
            pub fn get_index_of(this: &js::Array, value: JsValue) -> i32 {
                this.index_of(value)
            }

        "#)
        .file("test.ts", r#"
            import * as assert from "assert";
            import * as wasm from "./out";

            export function test() {
                let characters = ["a", "c", "x", "n"];
                let index = wasm.get_index_of(characters, "x");
                let notFoundIndex = wasm.get_index_of(characters, "z");

                assert.equal(index, 2);
                assert.equal(notFoundIndex, -1);
            }
        "#)
        .test()
}

update: I've done for Array

  • indexOf
  • fill
  • lastIndexOf
  • copyWithin
  • join

Assuming of course that I'm on the right track, though! I'm curious what you think would work for callback functions that are used in methods like find. I've read the bit about closures and the Closure type, but I'd have to implement some traits in order to get something like this to work

fn find(this: &Array, pred_fn: &Closure<&Fn(JsValue) -> bool>) -> JsValue;

but the compiler complains about unimplemented traits like RefIntoWasmAbi or something like that. Satisfying the compiler seems to go beyond the scope of this issue request, so I didn't dive any deeper. Considering how many methods utilize callbacks, I was hoping to get your 2 cents in.

Thanks!

@UtherII
Copy link

UtherII commented Jun 20, 2018

Shouldn't the doc comments (copied from the MDN summary) be updated to use the function names on the Rust side ?

For instance the decode_uri() function doc comment use the names decodeURI and encodeURI. I think it would be better to use the Rust names.

@jonathan-s
Copy link
Contributor

jonathan-s commented Jun 20, 2018

I followed the instructions here -> https://rustwasm.github.io/wasm-bindgen/contributing.html but when running cargo test 99% of the tests fail...

Solved by #277

@fitzgen
Copy link
Member Author

fitzgen commented Jun 20, 2018

@UtherII

Shouldn't the doc comments (copied from the MDN summary) be updated to use the function names on the Rust side ?

For instance the decode_uri() function doc comment use the names decodeURI and encodeURI. I think it would be better to use the Rust names.

Sure! Want to send a PR updating existing docs and adding that to the comment in src/js.rs?

@fitzgen
Copy link
Member Author

fitzgen commented Jun 20, 2018

@wismer

@fitzgen is this close to what you are looking for? (Array.prototype.indexOf)

Exactly! Just need to also add the summary from MDN as a doc comment, as described in the instructions comment in src/js.rs.

@wismer
Copy link
Contributor

wismer commented Jun 20, 2018

@fitzgen oh great! Would you prefer a PR for each individual one done, or have them batched together. I updated that comment with some other questions just a moment ago so let me know what you think!

@fitzgen
Copy link
Member Author

fitzgen commented Jun 20, 2018

@wismer, I would say do ~one PR per day, so batch however many that happens to be together :)

Individual commits for each bindings is still preferred :) 👍

@belfz
Copy link
Contributor

belfz commented Jun 20, 2018

Hello! For a good start, I'll take care of the Promise constructor and Promise.all() :)

@jonathan-s
Copy link
Contributor

Trying my hands on toString.

@coreh
Copy link

coreh commented Jun 20, 2018

@fitzgen

Additionally, .d.ts files don't give us information about whether a method can throw or not, so we would have to be conservative and assume that they always do, which isn't great to have at the most foundational layer of bindings.

Gotcha, that's indeed a current shortcoming of the TypeScript type system, hopefully they'll add support for typing exceptions in the future.

@fitzgen
Copy link
Member Author

fitzgen commented Jun 20, 2018

@belfz I think you want Closure<FnMut(JsValue) -> JsValue> rather than Closure<&Fn(JsValue)>. Let me know if that works.

If this doesn't work, we might want to start with non-closure taking methods.

@belfz
Copy link
Contributor

belfz commented Jun 20, 2018

@fitzgen thanks, I removed my last comment because I noticed I was wrong about the shape of Promise's executor ((resolve, reject) => {...} in plain JS). I'll take your hints into account.

@belfz
Copy link
Contributor

belfz commented Jun 20, 2018

Ok, as far as I can tell, the definition of Promise::new should look like:

#[wasm_bindgen(constructor)]
pub fn new(executor: &Closure<FnMut(Fn(JsValue), Fn(JsValue))>) -> Promise;

It is consistent with JavaScript's

new Promise( /* executor */ function(resolve, reject) { ... } );

where resolve and reject are callable.

However, this implementation throws:

92 | #[wasm_bindgen]
   |               ^ `core::ops::Fn(JsValue) + 'static` does not have a constant size known at compile-time

The cause of this error in that particular place is vague to me.

@fitzgen
Copy link
Member Author

fitzgen commented Jun 20, 2018

@belfz are you on IRC? can you share your branch?

As I mentioned earlier, it might be easier to start with non-closure methods first.

@dphm
Copy link

dphm commented Aug 19, 2018

@thomaseizinger I am using nvm, but assumed I qualified as "most users" 😂 Thanks anyway!

fitzgen added a commit to fitzgen/wasm-bindgen that referenced this issue Sep 6, 2018
fitzgen added a commit to fitzgen/wasm-bindgen that referenced this issue Sep 6, 2018
fitzgen added a commit to fitzgen/wasm-bindgen that referenced this issue Sep 6, 2018
fitzgen added a commit to fitzgen/wasm-bindgen that referenced this issue Sep 6, 2018
fitzgen added a commit to fitzgen/wasm-bindgen that referenced this issue Sep 6, 2018
fitzgen added a commit to fitzgen/wasm-bindgen that referenced this issue Sep 6, 2018
fitzgen added a commit to fitzgen/wasm-bindgen that referenced this issue Sep 6, 2018
@fitzgen
Copy link
Member Author

fitzgen commented Sep 6, 2018

I finished the WebAssembly bindings in #795, so we are down to only eight static methods of Object left -- that's it! Anyone want to claim any of them? ;)

@brisad
Copy link
Contributor

brisad commented Sep 7, 2018

@fitzgen I can start off with the first two: Object.defineProperties() and Object.defineProperty()

@fitzgen
Copy link
Member Author

fitzgen commented Sep 7, 2018

Great!

@brisad
Copy link
Contributor

brisad commented Sep 15, 2018

I can take the remaining six too :-)

@brisad
Copy link
Contributor

brisad commented Sep 19, 2018

Last four up for review! :-)

@fitzgen
Copy link
Member Author

fitzgen commented Sep 19, 2018

Thanks to the awesome work of @brisad, all that is left is String.raw :)

@fitzgen
Copy link
Member Author

fitzgen commented Sep 19, 2018

@afdw did the bindings for String.raw and we're all done! 🎉

Three months and one day from when this issue was opened to completion. That's almost 5 bindings per day -- not bad!

HUGE thank you to everyone who helped out! We couldn't have done it without you 💖

@fitzgen fitzgen closed this as completed Sep 19, 2018
Hywan added a commit to Hywan/wasm-bindgen that referenced this issue Sep 21, 2018
This patch adds a link to the crate's documentation. It also removes a reference to rustwasm#275, which is closed now.
@renatoathaydes
Copy link

renatoathaydes commented May 7, 2020

Sorry if this is not the right place to ask, but I am trying to use Intl::DateTimeFormat which seems to be covered by this ticket, and I can't get it work.
Could someone help me with that, I've asked about it on StackOverflow.

Thanks.

@Pauan
Copy link
Contributor

Pauan commented May 7, 2020

@renatoathaydes You have to do this:

let options = Intl::DateTimeFormat::new(&Array::new(), &Object::new()).resolved_options();
let tz = Reflect::get(&options, &JsValue::from("timeZone")).unwrap();

@renatoathaydes
Copy link

@Pauan thanks, that really helps. I think nothing can be done about having to use Reflect as the MDN docs regarding the returned object are pretty vague, but shouldn't there be a default constructor without arguments in DateTimeFormat?

@Pauan
Copy link
Contributor

Pauan commented May 7, 2020

shouldn't there be a default constructor without arguments in DateTimeFormat?

That sounds reasonable to me, but that would be a breaking change.

@elpiel
Copy link
Contributor

elpiel commented May 7, 2020

Maybe Default can be implemented for DateTimeFormat?
cc @renatoathaydes @Pauan

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
good first issue This is a good issue for people who have never contributed to wasm-bindgen before help wanted We could use some help fixing this issue! js-sys Issues related to the `js-sys` crate more-types Adding support for more Rust types to cross the boundary
Projects
None yet
Development

No branches or pull requests