-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Comments
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. |
@coreh we are building a TypeScript frontend to 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. |
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 ? |
How would multiple, optional arguments be handled for something like |
@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. |
@wismer we don't have great support for optional arguments at the moment, so for now it is best to do one of:
different choices may make sense for different methods. |
|
@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 |
@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). |
Also, the gh-pages should be fixed now! |
@fitzgen is this close to what you are looking for? ( 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
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 fn find(this: &Array, pred_fn: &Closure<&Fn(JsValue) -> bool>) -> JsValue; but the compiler complains about unimplemented traits like Thanks! |
Shouldn't the doc comments (copied from the MDN summary) be updated to use the function names on the Rust side ? For instance the |
Solved by #277 |
Sure! Want to send a PR updating existing docs and adding that to the comment in |
@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! |
@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 :) 👍 |
Hello! For a good start, I'll take care of the |
Trying my hands on |
Gotcha, that's indeed a current shortcoming of the TypeScript type system, hopefully they'll add support for typing exceptions in the future. |
@belfz I think you want If this doesn't work, we might want to start with non-closure taking methods. |
@fitzgen thanks, I removed my last comment because I noticed I was wrong about the shape of Promise's |
Ok, as far as I can tell, the definition of #[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 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. |
@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. |
@thomaseizinger I am using nvm, but assumed I qualified as "most users" 😂 Thanks anyway! |
I finished the WebAssembly bindings in #795, so we are down to only eight static methods of |
@fitzgen I can start off with the first two: |
Great! |
I can take the remaining six too :-) |
Last four up for review! :-) |
Thanks to the awesome work of @brisad, all that is left is |
@afdw did the bindings for 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 💖 |
This patch adds a link to the crate's documentation. It also removes a reference to rustwasm#275, which is closed now.
Sorry if this is not the right place to ask, but I am trying to use Thanks. |
@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(); |
@Pauan thanks, that really helps. I think nothing can be done about having to use |
That sounds reasonable to me, but that would be a breaking change. |
Maybe |
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:wasm-bindgen/crates/js-sys/src/lib.rs
Lines 28 to 44 in aa348f9
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()
The text was updated successfully, but these errors were encountered: