Skip to content

Commit dc4e785

Browse files
authored
Merge pull request #1019 from alexcrichton/rfc-5
Implement rustwasm/rfcs#5, implement `Deref` for imports and `structural` by default
2 parents f3b9c69 + cb246e3 commit dc4e785

File tree

27 files changed

+618
-246
lines changed

27 files changed

+618
-246
lines changed

crates/backend/src/codegen.rs

+18-4
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,7 @@ impl ToTokens for ast::ImportType {
535535
use wasm_bindgen::convert::RefFromWasmAbi;
536536
use wasm_bindgen::describe::WasmDescribe;
537537
use wasm_bindgen::{JsValue, JsCast};
538-
use wasm_bindgen::__rt::core::mem::ManuallyDrop;
538+
use wasm_bindgen::__rt::core;
539539

540540
impl WasmDescribe for #rust_name {
541541
fn describe() {
@@ -589,13 +589,13 @@ impl ToTokens for ast::ImportType {
589589

590590
impl RefFromWasmAbi for #rust_name {
591591
type Abi = <JsValue as RefFromWasmAbi>::Abi;
592-
type Anchor = ManuallyDrop<#rust_name>;
592+
type Anchor = core::mem::ManuallyDrop<#rust_name>;
593593

594594
#[inline]
595595
unsafe fn ref_from_abi(js: Self::Abi, extra: &mut Stack) -> Self::Anchor {
596596
let tmp = <JsValue as RefFromWasmAbi>::ref_from_abi(js, extra);
597-
ManuallyDrop::new(#rust_name {
598-
obj: ManuallyDrop::into_inner(tmp),
597+
core::mem::ManuallyDrop::new(#rust_name {
598+
obj: core::mem::ManuallyDrop::into_inner(tmp),
599599
})
600600
}
601601
}
@@ -657,6 +657,20 @@ impl ToTokens for ast::ImportType {
657657
};
658658
}).to_tokens(tokens);
659659

660+
let deref_target = match self.extends.first() {
661+
Some(target) => quote! { #target },
662+
None => quote! { JsValue },
663+
};
664+
(quote! {
665+
impl core::ops::Deref for #rust_name {
666+
type Target = #deref_target;
667+
668+
#[inline]
669+
fn deref(&self) -> &#deref_target {
670+
self.as_ref()
671+
}
672+
}
673+
}).to_tokens(tokens);
660674
for superclass in self.extends.iter() {
661675
(quote! {
662676
impl From<#rust_name> for #superclass {

crates/cli-support/src/js/js2rust.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
413413
name = name
414414
));
415415
}
416-
self.rust_arguments.push(format!("{} ? 1 : 0", name));
416+
self.rust_arguments.push(format!("{}", name));
417417
}
418418
Descriptor::Char => {
419419
self.js_arguments.push((name.clone(), "string".to_string()));

crates/cli-support/src/js/mod.rs

+82-105
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use std::collections::{HashMap, HashSet};
2-
use std::fmt::Write;
32
use std::mem;
43

54
use decode;
@@ -65,6 +64,18 @@ pub struct SubContext<'a, 'b: 'a> {
6564
pub vendor_prefixes: HashMap<&'b str, Vec<&'b str>>,
6665
}
6766

67+
pub enum ImportTarget {
68+
Function(String),
69+
Method(String),
70+
Constructor(String),
71+
StructuralMethod(String),
72+
StructuralGetter(Option<String>, String),
73+
StructuralSetter(Option<String>, String),
74+
StructuralIndexingGetter(Option<String>),
75+
StructuralIndexingSetter(Option<String>),
76+
StructuralIndexingDeleter(Option<String>),
77+
}
78+
6879
const INITIAL_SLAB_VALUES: &[&str] = &["undefined", "null", "true", "false"];
6980

7081
impl<'a> Context<'a> {
@@ -1944,7 +1955,7 @@ impl<'a, 'b> SubContext<'a, 'b> {
19441955
Some(d) => d,
19451956
};
19461957

1947-
let target = self.generated_import_target(info, import, &descriptor)?;
1958+
let target = self.generated_import_target(info, import)?;
19481959

19491960
let js = Rust2Js::new(self.cx)
19501961
.catch(import.catch)
@@ -1959,137 +1970,103 @@ impl<'a, 'b> SubContext<'a, 'b> {
19591970
&mut self,
19601971
info: &decode::Import<'b>,
19611972
import: &decode::ImportFunction,
1962-
descriptor: &Descriptor,
1963-
) -> Result<String, Error> {
1973+
) -> Result<ImportTarget, Error> {
19641974
let method_data = match &import.method {
19651975
Some(data) => data,
19661976
None => {
19671977
let name = self.import_name(info, &import.function.name)?;
1968-
return Ok(if name.contains(".") {
1969-
self.cx.global(&format!(
1970-
"
1971-
const {}_target = {};
1972-
",
1973-
import.shim, name
1974-
));
1975-
format!("{}_target", import.shim)
1976-
} else {
1977-
name
1978-
});
1978+
if import.structural || !name.contains(".") {
1979+
return Ok(ImportTarget::Function(name))
1980+
}
1981+
self.cx.global(&format!("const {}_target = {};", import.shim, name));
1982+
let target = format!("{}_target", import.shim);
1983+
return Ok(ImportTarget::Function(target))
19791984
}
19801985
};
19811986

19821987
let class = self.import_name(info, &method_data.class)?;
19831988
let op = match &method_data.kind {
1984-
decode::MethodKind::Constructor => return Ok(format!("new {}", class)),
1989+
decode::MethodKind::Constructor => {
1990+
return Ok(ImportTarget::Constructor(class.to_string()))
1991+
}
19851992
decode::MethodKind::Operation(op) => op,
19861993
};
1987-
let target = if import.structural {
1988-
let location = if op.is_static { &class } else { "this" };
1994+
if import.structural {
1995+
let class = if op.is_static { Some(class.clone()) } else { None };
19891996

1990-
match &op.kind {
1997+
return Ok(match &op.kind {
19911998
decode::OperationKind::Regular => {
1992-
let nargs = descriptor.unwrap_function().arguments.len();
1993-
let mut s = format!("function(");
1994-
for i in 0..nargs - 1 {
1995-
if i > 0 {
1996-
drop(write!(s, ", "));
1997-
}
1998-
drop(write!(s, "x{}", i));
1999+
let name = import.function.name.to_string();
2000+
match class {
2001+
Some(c) => ImportTarget::Function(format!("{}.{}", c, name)),
2002+
None => ImportTarget::StructuralMethod(name),
19992003
}
2000-
s.push_str(") { \nreturn this.");
2001-
s.push_str(&import.function.name);
2002-
s.push_str("(");
2003-
for i in 0..nargs - 1 {
2004-
if i > 0 {
2005-
drop(write!(s, ", "));
2006-
}
2007-
drop(write!(s, "x{}", i));
2008-
}
2009-
s.push_str(");\n}");
2010-
s
2011-
}
2012-
decode::OperationKind::Getter(g) => format!(
2013-
"function() {{
2014-
return {}.{};
2015-
}}",
2016-
location, g
2017-
),
2018-
decode::OperationKind::Setter(s) => format!(
2019-
"function(y) {{
2020-
{}.{} = y;
2021-
}}",
2022-
location, s
2023-
),
2024-
decode::OperationKind::IndexingGetter => format!(
2025-
"function(y) {{
2026-
return {}[y];
2027-
}}",
2028-
location
2029-
),
2030-
decode::OperationKind::IndexingSetter => format!(
2031-
"function(y, z) {{
2032-
{}[y] = z;
2033-
}}",
2034-
location
2035-
),
2036-
decode::OperationKind::IndexingDeleter => format!(
2037-
"function(y) {{
2038-
delete {}[y];
2039-
}}",
2040-
location
2041-
),
2042-
}
2043-
} else {
2044-
let target = format!("typeof {0} === 'undefined' ? null : {}{}",
2045-
class,
2046-
if op.is_static { "" } else { ".prototype" });
2047-
let (mut target, name) = match &op.kind {
2048-
decode::OperationKind::Regular => {
2049-
(format!("{}.{}", target, import.function.name), &import.function.name)
20502004
}
20512005
decode::OperationKind::Getter(g) => {
2052-
self.cx.expose_get_inherited_descriptor();
2053-
(format!(
2054-
"GetOwnOrInheritedPropertyDescriptor({}, '{}').get",
2055-
target, g,
2056-
), g)
2006+
ImportTarget::StructuralGetter(class, g.to_string())
20572007
}
20582008
decode::OperationKind::Setter(s) => {
2059-
self.cx.expose_get_inherited_descriptor();
2060-
(format!(
2061-
"GetOwnOrInheritedPropertyDescriptor({}, '{}').set",
2062-
target, s,
2063-
), s)
2009+
ImportTarget::StructuralSetter(class, s.to_string())
20642010
}
20652011
decode::OperationKind::IndexingGetter => {
2066-
panic!("indexing getter should be structural")
2012+
ImportTarget::StructuralIndexingGetter(class)
20672013
}
20682014
decode::OperationKind::IndexingSetter => {
2069-
panic!("indexing setter should be structural")
2015+
ImportTarget::StructuralIndexingSetter(class)
20702016
}
20712017
decode::OperationKind::IndexingDeleter => {
2072-
panic!("indexing deleter should be structural")
2018+
ImportTarget::StructuralIndexingDeleter(class)
20732019
}
2074-
};
2075-
target.push_str(&format!(" || function() {{
2076-
throw new Error(`wasm-bindgen: {}.{} does not exist`);
2077-
}}", class, name));
2078-
if op.is_static {
2079-
target.insert(0, '(');
2080-
target.push_str(").bind(");
2081-
target.push_str(&class);
2082-
target.push_str(")");
2083-
}
2084-
target
2020+
})
2021+
}
2022+
2023+
let target = format!("typeof {0} === 'undefined' ? null : {}{}",
2024+
class,
2025+
if op.is_static { "" } else { ".prototype" });
2026+
let (mut target, name) = match &op.kind {
2027+
decode::OperationKind::Regular => {
2028+
(format!("{}.{}", target, import.function.name), &import.function.name)
2029+
}
2030+
decode::OperationKind::Getter(g) => {
2031+
self.cx.expose_get_inherited_descriptor();
2032+
(format!(
2033+
"GetOwnOrInheritedPropertyDescriptor({}, '{}').get",
2034+
target, g,
2035+
), g)
2036+
}
2037+
decode::OperationKind::Setter(s) => {
2038+
self.cx.expose_get_inherited_descriptor();
2039+
(format!(
2040+
"GetOwnOrInheritedPropertyDescriptor({}, '{}').set",
2041+
target, s,
2042+
), s)
2043+
}
2044+
decode::OperationKind::IndexingGetter => {
2045+
panic!("indexing getter should be structural")
2046+
}
2047+
decode::OperationKind::IndexingSetter => {
2048+
panic!("indexing setter should be structural")
2049+
}
2050+
decode::OperationKind::IndexingDeleter => {
2051+
panic!("indexing deleter should be structural")
2052+
}
20852053
};
2054+
target.push_str(&format!(" || function() {{
2055+
throw new Error(`wasm-bindgen: {}.{} does not exist`);
2056+
}}", class, name));
2057+
if op.is_static {
2058+
target.insert(0, '(');
2059+
target.push_str(").bind(");
2060+
target.push_str(&class);
2061+
target.push_str(")");
2062+
}
20862063

20872064
self.cx.global(&format!("const {}_target = {};", import.shim, target));
2088-
Ok(format!(
2089-
"{}_target{}",
2090-
import.shim,
2091-
if op.is_static { "" } else { ".call" }
2092-
))
2065+
Ok(if op.is_static {
2066+
ImportTarget::Function(format!("{}_target", import.shim))
2067+
} else {
2068+
ImportTarget::Method(format!("{}_target", import.shim))
2069+
})
20932070
}
20942071

20952072
fn generate_import_type(

0 commit comments

Comments
 (0)