Merge branch 'master' into reexporting_in_2018

This commit is contained in:
konstin 2019-03-18 21:38:18 +01:00 committed by GitHub
commit 42c1cdd8bf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 260 additions and 54 deletions

View File

@ -79,6 +79,7 @@ pub struct Import {
pub enum ImportModule {
None,
Named(String, Span),
RawNamed(String, Span),
Inline(usize, Span),
}
@ -96,6 +97,10 @@ impl Hash for ImportModule {
2u8.hash(h);
idx.hash(h);
}
ImportModule::RawNamed(name, _) => {
3u8.hash(h);
name.hash(h);
}
}
}
}

View File

@ -844,6 +844,18 @@ impl ToTokens for ast::ImportEnum {
}
}
#[allow(clippy::all)]
impl wasm_bindgen::convert::OptionIntoWasmAbi for #name {
#[inline]
fn none() -> Self::Abi { Object::none() }
}
#[allow(clippy::all)]
impl wasm_bindgen::convert::OptionFromWasmAbi for #name {
#[inline]
fn is_none(abi: &Self::Abi) -> bool { Object::is_none(abi) }
}
#[allow(clippy::all)]
impl From<#name> for wasm_bindgen::JsValue {
fn from(obj: #name) -> wasm_bindgen::JsValue {

View File

@ -208,6 +208,7 @@ fn shared_import<'a>(i: &'a ast::Import, intern: &'a Interner) -> Result<Import<
ast::ImportModule::Named(m, span) => {
ImportModule::Named(intern.resolve_import_module(m, *span)?)
}
ast::ImportModule::RawNamed(m, _span) => ImportModule::RawNamed(intern.intern_str(m)),
ast::ImportModule::Inline(idx, _) => ImportModule::Inline(*idx as u32),
ast::ImportModule::None => ImportModule::None,
},

View File

@ -2836,6 +2836,7 @@ impl<'a, 'b> SubContext<'a, 'b> {
// not sure how to import them.
let is_local_snippet = match import.module {
decode::ImportModule::Named(s) => self.cx.local_modules.contains_key(s),
decode::ImportModule::RawNamed(_) => false,
decode::ImportModule::Inline(_) => true,
decode::ImportModule::None => false,
};
@ -2921,11 +2922,13 @@ impl<'a, 'b> SubContext<'a, 'b> {
name,
field,
},
decode::ImportModule::Named(module) => Import::Module {
module,
name,
field,
},
decode::ImportModule::Named(module) | decode::ImportModule::RawNamed(module) => {
Import::Module {
module,
name,
field,
}
}
decode::ImportModule::Inline(idx) => {
let offset = *self
.cx

View File

@ -33,6 +33,7 @@ macro_rules! attrgen {
(static_method_of, StaticMethodOf(Span, Ident)),
(js_namespace, JsNamespace(Span, Ident)),
(module, Module(Span, String, Span)),
(raw_module, RawModule(Span, String, Span)),
(inline_js, InlineJs(Span, String, Span)),
(getter, Getter(Span, Option<Ident>)),
(setter, Setter(Span, Option<Ident>)),
@ -1085,24 +1086,28 @@ impl MacroParse<BindgenAttrs> for syn::ItemForeignMod {
));
}
}
let module = match opts.module() {
Some((name, span)) => {
if opts.inline_js().is_some() {
let msg = "cannot specify both `module` and `inline_js`";
errors.push(Diagnostic::span_error(span, msg));
}
ast::ImportModule::Named(name.to_string(), span)
let module = if let Some((name, span)) = opts.module() {
if opts.inline_js().is_some() {
let msg = "cannot specify both `module` and `inline_js`";
errors.push(Diagnostic::span_error(span, msg));
}
None => {
match opts.inline_js() {
Some((js, span)) => {
let i = program.inline_js.len();
program.inline_js.push(js.to_string());
ast::ImportModule::Inline(i, span)
}
None => ast::ImportModule::None
}
if opts.raw_module().is_some() {
let msg = "cannot specify both `module` and `raw_module`";
errors.push(Diagnostic::span_error(span, msg));
}
ast::ImportModule::Named(name.to_string(), span)
} else if let Some((name, span)) = opts.raw_module() {
if opts.inline_js().is_some() {
let msg = "cannot specify both `raw_module` and `inline_js`";
errors.push(Diagnostic::span_error(span, msg));
}
ast::ImportModule::RawNamed(name.to_string(), span)
} else if let Some((js, span)) = opts.inline_js() {
let i = program.inline_js.len();
program.inline_js.push(js.to_string());
ast::ImportModule::Inline(i, span)
} else {
ast::ImportModule::None
};
for item in self.items.into_iter() {
if let Err(e) = item.macro_parse(program, module.clone()) {

View File

@ -28,6 +28,7 @@ macro_rules! shared_api {
enum ImportModule<'a> {
None,
Named(&'a str),
RawNamed(&'a str),
Inline(u32),
}

View File

@ -1,11 +0,0 @@
import * as wbg from './pkg/typescript_tests';
import * as wasm from './pkg/typescript_tests_bg';
const a1: (a: string) => void = wbg.greet;
const a2: (a: number, b: number) => void = wasm.greet;
const a3: WebAssembly.Memory = wasm.memory;
const c = new wbg.A();
wbg.A.other();
c.foo();
c.free();

View File

@ -0,0 +1,11 @@
use wasm_bindgen::prelude::*;
#[wasm_bindgen(typescript_custom_section)]
const TS_INTERFACE_EXPORT: &'static str = r"
interface Height { height: number; }
";
#[wasm_bindgen]
pub struct Person {
pub height: u32,
}

View File

@ -0,0 +1,3 @@
import * as wbg from '../pkg/typescript_tests';
const height: wbg.Height = new wbg.Person();

View File

@ -1,20 +1,4 @@
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn greet(_: &str) {}
#[wasm_bindgen]
struct A {
}
#[wasm_bindgen]
impl A {
#[wasm_bindgen(constructor)]
pub fn new() -> A {
A {}
}
pub fn other() {}
pub fn foo(&self) {}
}
mod custom_section;
mod opt_args_and_ret;
mod simple_fn;
mod simple_struct;

View File

@ -0,0 +1,3 @@
import * as wasm from '../pkg/typescript_tests_bg';
const memory: WebAssembly.Memory = wasm.memory;

View File

@ -0,0 +1,6 @@
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn opt_fn(_a: Option<i32>) -> Option<i32> {
None
}

View File

@ -0,0 +1,3 @@
import * as wbg from '../pkg/typescript_tests';
const opt_fn: (a: number | undefined) => number | undefined = wbg.opt_fn;

View File

@ -0,0 +1,4 @@
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn greet(_: &str) {}

View File

@ -0,0 +1,5 @@
import * as wbg from '../pkg/typescript_tests';
import * as wasm from '../pkg/typescript_tests_bg';
const wbg_greet: (a: string) => void = wbg.greet;
const wasm_greet: (a: number, b: number) => void = wasm.greet;

View File

@ -0,0 +1,17 @@
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub struct A {
}
#[wasm_bindgen]
impl A {
#[wasm_bindgen(constructor)]
pub fn new() -> A {
A {}
}
pub fn other() {}
pub fn foo(&self) {}
}

View File

@ -0,0 +1,6 @@
import * as wbg from '../pkg/typescript_tests';
const a = new wbg.A();
wbg.A.other();
a.foo();
a.free();

View File

@ -9,6 +9,6 @@
"baseUrl": "."
},
"include": [
"index.ts"
"src/*.ts"
]
}

View File

@ -814,6 +814,9 @@ RtcRtpSender = []
RtcRtpSourceEntry = []
RtcRtpSourceEntryType = []
RtcRtpSynchronizationSource = []
RtcRtpTransceiver = []
RtcRtpTransceiverDirection = []
RtcRtpTransceiverInit = []
RtcRtxParameters = []
RtcSdpType = []
RtcSessionDescription = []
@ -826,6 +829,7 @@ RtcStatsReport = []
RtcStatsReportInternal = []
RtcStatsType = []
RtcTrackEvent = []
RtcTrackEventInit = []
RtcTransportStats = []
RtcdtmfSender = []
RtcdtmfToneChangeEvent = []

View File

@ -48,6 +48,7 @@ pub mod pre_element;
pub mod progress_element;
pub mod quote_element;
pub mod response;
pub mod rtc_rtp_transceiver_direction;
pub mod script_element;
pub mod select_element;
pub mod slot_element;

View File

@ -0,0 +1,92 @@
use wasm_bindgen::{prelude::*, JsCast};
use wasm_bindgen_futures::JsFuture;
use wasm_bindgen_test::*;
use futures::{
future::{ok, IntoFuture},
Future,
};
use web_sys::{
RtcPeerConnection, RtcRtpTransceiver, RtcRtpTransceiverDirection, RtcRtpTransceiverInit,
RtcSessionDescriptionInit,
};
#[wasm_bindgen(
inline_js = "export function is_unified_avail() { return Object.keys(RTCRtpTransceiver.prototype).indexOf('currentDirection')>-1; }"
)]
extern "C" {
/// Available in FF since forever, in Chrome since 72, in Safari since 12.1
fn is_unified_avail() -> bool;
}
#[wasm_bindgen_test(async)]
fn rtc_rtp_transceiver_direction() -> Box<dyn Future<Item = (), Error = JsValue>> {
if !is_unified_avail() {
return Box::new(Ok(()).into_future());
}
let mut tr_init: RtcRtpTransceiverInit = RtcRtpTransceiverInit::new();
let pc1: RtcPeerConnection = RtcPeerConnection::new().unwrap();
let tr1: RtcRtpTransceiver = pc1.add_transceiver_with_str_and_init(
"audio",
tr_init.direction(RtcRtpTransceiverDirection::Sendonly),
);
assert_eq!(tr1.direction(), RtcRtpTransceiverDirection::Sendonly);
assert_eq!(tr1.current_direction(), None);
let pc2: RtcPeerConnection = RtcPeerConnection::new().unwrap();
let r = exchange_sdps(pc1, pc2).and_then(move |(_, p2)| {
assert_eq!(tr1.direction(), RtcRtpTransceiverDirection::Sendonly);
assert_eq!(
tr1.current_direction(),
Some(RtcRtpTransceiverDirection::Sendonly)
);
let tr2: RtcRtpTransceiver = js_sys::try_iter(&p2.get_transceivers())
.unwrap()
.unwrap()
.next()
.unwrap()
.unwrap()
.unchecked_into();
assert_eq!(tr2.direction(), RtcRtpTransceiverDirection::Recvonly);
assert_eq!(
tr2.current_direction(),
Some(RtcRtpTransceiverDirection::Recvonly)
);
Ok(())
});
Box::new(r)
}
fn exchange_sdps(
p1: RtcPeerConnection,
p2: RtcPeerConnection,
) -> impl Future<Item = (RtcPeerConnection, RtcPeerConnection), Error = JsValue> {
JsFuture::from(p1.create_offer())
.and_then(move |offer| {
let offer = offer.unchecked_into::<RtcSessionDescriptionInit>();
JsFuture::from(p1.set_local_description(&offer)).join4(
JsFuture::from(p2.set_remote_description(&offer)),
Ok(p1),
Ok(p2),
)
})
.and_then(|(_, _, p1, p2)| JsFuture::from(p2.create_answer()).join3(Ok(p1), Ok(p2)))
.and_then(|(answer, p1, p2)| {
let answer = answer.unchecked_into::<RtcSessionDescriptionInit>();
JsFuture::from(p2.set_local_description(&answer)).join4(
JsFuture::from(p1.set_remote_description(&answer)),
Ok(p1),
Ok(p2),
)
})
.and_then(|(_, _, p1, p2)| Ok((p1, p2)))
}

View File

@ -18,4 +18,12 @@ global.Shape = class Shape {
getShape() {
return this.kind;
}
get shapeTypeNone() {
return null;
}
get shapeTypeSome() {
return this.kind;
}
};

View File

@ -35,3 +35,17 @@ fn invalid_enum_return() {
_ => {} // Success
};
}
#[wasm_bindgen_test]
fn read_optional_enum_attribute_none() {
let shape = Shape::new(ShapeType::Circle).unwrap();
let shape_type: Option<ShapeType> = shape.shape_type_none();
assert_eq!(shape_type, None);
}
#[wasm_bindgen_test]
fn read_optional_enum_attribute_some() {
let shape = Shape::new(ShapeType::Circle).unwrap();
let shape_type: Option<ShapeType> = shape.shape_type_some();
assert_eq!(shape_type, Some(ShapeType::Circle));
}

View File

@ -12,4 +12,8 @@ interface Shape {
[Pure]
ShapeType getShape();
readonly attribute ShapeType? shapeTypeNone;
readonly attribute ShapeType? shapeTypeSome;
};

View File

@ -66,6 +66,7 @@
- [`js_namespace`](./reference/attributes/on-js-imports/js_namespace.md)
- [`method`](./reference/attributes/on-js-imports/method.md)
- [`module = "blah"`](./reference/attributes/on-js-imports/module.md)
- [`raw_module = "blah"`](./reference/attributes/on-js-imports/raw_module.md)
- [`static_method_of = Blah`](./reference/attributes/on-js-imports/static_method_of.md)
- [`structural`](./reference/attributes/on-js-imports/structural.md)
- [`variadic`](./reference/attributes/on-js-imports/variadic.md)

View File

@ -31,3 +31,8 @@ generates JavaScript import glue like:
```js
let illmatic = this.illmatic;
```
Note that if the string specified with `module` starts with `./`, `../`, or `/`
then it's interpreted as a path to a [local JS snippet](../../js-snippets.html).
If this doesn't work for your use case you might be interested in the
[`raw_module` attribute](raw_module.html)

View File

@ -0,0 +1,19 @@
# `raw_module = "blah"`
This attribute performs exactly the same purpose as the [`module`
attribute](module.html) on JS imports, but it does not attempt to interpret
paths starting with `./`, `../`, or `/` as JS snippets. For example:
```rust
#[wasm_bindgen(raw_module = "./some/js/file.js")]
extern "C" {
fn the_function();
}
```
Note that if you use this attribute with a relative or absolute path, it's
likely up to the final bundler or project to assign meaning to that path. This
typically means that the JS file or module will be resolved relative to the
final location of the wasm file itself. That means that `raw_module` is likely
unsuitable for libraries on crates.io, but may be usable within end-user
applications.

View File

@ -4,7 +4,7 @@
"serve": "webpack-dev-server -p"
},
"devDependencies": {
"@wasm-tool/wasm-pack-plugin": "0.2.5",
"@wasm-tool/wasm-pack-plugin": "0.2.7",
"html-webpack-plugin": "^3.2.0",
"text-encoding": "^0.7.0",
"webpack": "^4.29.4",