mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-03-28 07:51:07 +00:00
Merge pull request #761 from alexcrichton/more-globals
web-sys: Add support for `Global`-scope methods
This commit is contained in:
commit
1565459107
@ -99,6 +99,10 @@ pub enum ImportFunctionKind {
|
|||||||
ty: syn::Type,
|
ty: syn::Type,
|
||||||
kind: MethodKind,
|
kind: MethodKind,
|
||||||
},
|
},
|
||||||
|
ScopedMethod {
|
||||||
|
ty: syn::Type,
|
||||||
|
operation: Operation,
|
||||||
|
},
|
||||||
Normal,
|
Normal,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -407,6 +411,29 @@ impl ImportFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn shared(&self) -> shared::ImportFunction {
|
fn shared(&self) -> shared::ImportFunction {
|
||||||
|
let shared_operation = |operation: &Operation| {
|
||||||
|
let is_static = operation.is_static;
|
||||||
|
let kind = match &operation.kind {
|
||||||
|
OperationKind::Regular => shared::OperationKind::Regular,
|
||||||
|
OperationKind::Getter(g) => {
|
||||||
|
let g = g.as_ref().map(|g| g.to_string());
|
||||||
|
shared::OperationKind::Getter(
|
||||||
|
g.unwrap_or_else(|| self.infer_getter_property()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
OperationKind::Setter(s) => {
|
||||||
|
let s = s.as_ref().map(|s| s.to_string());
|
||||||
|
shared::OperationKind::Setter(
|
||||||
|
s.unwrap_or_else(|| self.infer_setter_property()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
OperationKind::IndexingGetter => shared::OperationKind::IndexingGetter,
|
||||||
|
OperationKind::IndexingSetter => shared::OperationKind::IndexingSetter,
|
||||||
|
OperationKind::IndexingDeleter => shared::OperationKind::IndexingDeleter,
|
||||||
|
};
|
||||||
|
shared::Operation { is_static, kind }
|
||||||
|
};
|
||||||
|
|
||||||
let method = match self.kind {
|
let method = match self.kind {
|
||||||
ImportFunctionKind::Method {
|
ImportFunctionKind::Method {
|
||||||
ref class,
|
ref class,
|
||||||
@ -415,34 +442,21 @@ impl ImportFunction {
|
|||||||
} => {
|
} => {
|
||||||
let kind = match kind {
|
let kind = match kind {
|
||||||
MethodKind::Constructor => shared::MethodKind::Constructor,
|
MethodKind::Constructor => shared::MethodKind::Constructor,
|
||||||
MethodKind::Operation(Operation { is_static, kind }) => {
|
MethodKind::Operation(op) => {
|
||||||
let is_static = *is_static;
|
shared::MethodKind::Operation(shared_operation(op))
|
||||||
let kind = match kind {
|
|
||||||
OperationKind::Regular => shared::OperationKind::Regular,
|
|
||||||
OperationKind::Getter(g) => {
|
|
||||||
let g = g.as_ref().map(|g| g.to_string());
|
|
||||||
shared::OperationKind::Getter(
|
|
||||||
g.unwrap_or_else(|| self.infer_getter_property()),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
OperationKind::Setter(s) => {
|
|
||||||
let s = s.as_ref().map(|s| s.to_string());
|
|
||||||
shared::OperationKind::Setter(
|
|
||||||
s.unwrap_or_else(|| self.infer_setter_property()),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
OperationKind::IndexingGetter => shared::OperationKind::IndexingGetter,
|
|
||||||
OperationKind::IndexingSetter => shared::OperationKind::IndexingSetter,
|
|
||||||
OperationKind::IndexingDeleter => shared::OperationKind::IndexingDeleter,
|
|
||||||
};
|
|
||||||
shared::MethodKind::Operation(shared::Operation { is_static, kind })
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Some(shared::MethodData {
|
Some(shared::MethodData {
|
||||||
class: class.clone(),
|
class: Some(class.clone()),
|
||||||
kind,
|
kind,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
ImportFunctionKind::ScopedMethod { ref operation, .. } => {
|
||||||
|
Some(shared::MethodData {
|
||||||
|
class: None,
|
||||||
|
kind: shared::MethodKind::Operation(shared_operation(operation)),
|
||||||
|
})
|
||||||
|
}
|
||||||
ImportFunctionKind::Normal => None,
|
ImportFunctionKind::Normal => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -784,6 +784,9 @@ impl TryToTokens for ast::ImportFunction {
|
|||||||
}
|
}
|
||||||
class_ty = Some(ty);
|
class_ty = Some(ty);
|
||||||
}
|
}
|
||||||
|
ast::ImportFunctionKind::ScopedMethod { ref ty, .. } => {
|
||||||
|
class_ty = Some(ty);
|
||||||
|
}
|
||||||
ast::ImportFunctionKind::Normal => {}
|
ast::ImportFunctionKind::Normal => {}
|
||||||
}
|
}
|
||||||
let vis = &self.function.rust_vis;
|
let vis = &self.function.rust_vis;
|
||||||
|
@ -246,6 +246,7 @@ impl ImportedTypes for ast::ImportFunctionKind {
|
|||||||
{
|
{
|
||||||
match self {
|
match self {
|
||||||
ast::ImportFunctionKind::Method { ty, .. } => ty.imported_types(f),
|
ast::ImportFunctionKind::Method { ty, .. } => ty.imported_types(f),
|
||||||
|
ast::ImportFunctionKind::ScopedMethod { ty, .. } => ty.imported_types(f),
|
||||||
ast::ImportFunctionKind::Normal => {}
|
ast::ImportFunctionKind::Normal => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1959,127 +1959,27 @@ impl<'a, 'b> SubContext<'a, 'b> {
|
|||||||
Some(d) => d,
|
Some(d) => d,
|
||||||
};
|
};
|
||||||
|
|
||||||
let target = match &import.method {
|
let target = self.generated_import_target(info, import, &descriptor)?;
|
||||||
Some(shared::MethodData { class, kind }) => {
|
|
||||||
let class = self.import_name(info, class)?;
|
|
||||||
match kind {
|
|
||||||
shared::MethodKind::Constructor => format!("new {}", class),
|
|
||||||
shared::MethodKind::Operation(shared::Operation { is_static, kind }) => {
|
|
||||||
let target = if import.structural {
|
|
||||||
let location = if *is_static { &class } else { "this" };
|
|
||||||
|
|
||||||
match kind {
|
let js = Rust2Js::new(self.cx)
|
||||||
shared::OperationKind::Regular => {
|
.catch(import.catch)
|
||||||
let nargs = descriptor.unwrap_function().arguments.len();
|
.process(descriptor.unwrap_function())?
|
||||||
let mut s = format!("function(");
|
.finish(&target);
|
||||||
for i in 0..nargs - 1 {
|
self.cx.export(&import.shim, &js, None);
|
||||||
if i > 0 {
|
Ok(())
|
||||||
drop(write!(s, ", "));
|
}
|
||||||
}
|
|
||||||
drop(write!(s, "x{}", i));
|
|
||||||
}
|
|
||||||
s.push_str(") { \nreturn this.");
|
|
||||||
s.push_str(&import.function.name);
|
|
||||||
s.push_str("(");
|
|
||||||
for i in 0..nargs - 1 {
|
|
||||||
if i > 0 {
|
|
||||||
drop(write!(s, ", "));
|
|
||||||
}
|
|
||||||
drop(write!(s, "x{}", i));
|
|
||||||
}
|
|
||||||
s.push_str(");\n}");
|
|
||||||
s
|
|
||||||
}
|
|
||||||
shared::OperationKind::Getter(g) => format!(
|
|
||||||
"function() {{
|
|
||||||
return {}.{};
|
|
||||||
}}",
|
|
||||||
location, g
|
|
||||||
),
|
|
||||||
shared::OperationKind::Setter(s) => format!(
|
|
||||||
"function(y) {{
|
|
||||||
{}.{} = y;
|
|
||||||
}}",
|
|
||||||
location, s
|
|
||||||
),
|
|
||||||
shared::OperationKind::IndexingGetter => format!(
|
|
||||||
"function(y) {{
|
|
||||||
return {}[y];
|
|
||||||
}}",
|
|
||||||
location
|
|
||||||
),
|
|
||||||
shared::OperationKind::IndexingSetter => format!(
|
|
||||||
"function(y, z) {{
|
|
||||||
{}[y] = z;
|
|
||||||
}}",
|
|
||||||
location
|
|
||||||
),
|
|
||||||
shared::OperationKind::IndexingDeleter => format!(
|
|
||||||
"function(y) {{
|
|
||||||
delete {}[y];
|
|
||||||
}}",
|
|
||||||
location
|
|
||||||
),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let (location, binding) = if *is_static {
|
|
||||||
("", format!(".bind({})", class))
|
|
||||||
} else {
|
|
||||||
(".prototype", "".into())
|
|
||||||
};
|
|
||||||
|
|
||||||
match kind {
|
fn generated_import_target(
|
||||||
shared::OperationKind::Regular => {
|
&mut self,
|
||||||
format!("{}{}.{}{}", class, location, import.function.name, binding)
|
info: &shared::Import,
|
||||||
}
|
import: &shared::ImportFunction,
|
||||||
shared::OperationKind::Getter(g) => {
|
descriptor: &Descriptor,
|
||||||
self.cx.expose_get_inherited_descriptor();
|
) -> Result<String, Error> {
|
||||||
format!(
|
let method_data = match &import.method {
|
||||||
"GetOwnOrInheritedPropertyDescriptor({}{}, '{}').get{}",
|
Some(data) => data,
|
||||||
class, location, g, binding,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
shared::OperationKind::Setter(s) => {
|
|
||||||
self.cx.expose_get_inherited_descriptor();
|
|
||||||
format!(
|
|
||||||
"GetOwnOrInheritedPropertyDescriptor({}{}, '{}').set{}",
|
|
||||||
class, location, s, binding,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
shared::OperationKind::IndexingGetter => panic!("indexing getter should be structural"),
|
|
||||||
shared::OperationKind::IndexingSetter => panic!("indexing setter should be structural"),
|
|
||||||
shared::OperationKind::IndexingDeleter => panic!("indexing deleter should be structural"),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let fallback = if import.structural {
|
|
||||||
"".to_string()
|
|
||||||
} else {
|
|
||||||
format!(
|
|
||||||
" || function() {{
|
|
||||||
throw new Error(`wasm-bindgen: {} does not exist`);
|
|
||||||
}}",
|
|
||||||
target
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
self.cx.global(&format!(
|
|
||||||
"
|
|
||||||
const {}_target = {} {} ;
|
|
||||||
",
|
|
||||||
import.shim, target, fallback
|
|
||||||
));
|
|
||||||
format!(
|
|
||||||
"{}_target{}",
|
|
||||||
import.shim,
|
|
||||||
if *is_static { "" } else { ".call" }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => {
|
None => {
|
||||||
let name = self.import_name(info, &import.function.name)?;
|
let name = self.import_name(info, &import.function.name)?;
|
||||||
if name.contains(".") {
|
return Ok(if name.contains(".") {
|
||||||
self.cx.global(&format!(
|
self.cx.global(&format!(
|
||||||
"
|
"
|
||||||
const {}_target = {};
|
const {}_target = {};
|
||||||
@ -2089,16 +1989,145 @@ impl<'a, 'b> SubContext<'a, 'b> {
|
|||||||
format!("{}_target", import.shim)
|
format!("{}_target", import.shim)
|
||||||
} else {
|
} else {
|
||||||
name
|
name
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let js = Rust2Js::new(self.cx)
|
let class = match &method_data.class {
|
||||||
.catch(import.catch)
|
Some(class) => self.import_name(info, class)?,
|
||||||
.process(descriptor.unwrap_function())?
|
None => {
|
||||||
.finish(&target);
|
let op = match &method_data.kind {
|
||||||
self.cx.export(&import.shim, &js, None);
|
shared::MethodKind::Operation(op) => op,
|
||||||
Ok(())
|
shared::MethodKind::Constructor => {
|
||||||
|
bail!("\"no class\" methods cannot be constructors")
|
||||||
|
}
|
||||||
|
};
|
||||||
|
match &op.kind {
|
||||||
|
shared::OperationKind::Regular => {
|
||||||
|
return Ok(import.function.name.to_string())
|
||||||
|
}
|
||||||
|
shared::OperationKind::Getter(g) => {
|
||||||
|
return Ok(format!("(() => {})", g));
|
||||||
|
}
|
||||||
|
shared::OperationKind::Setter(g) => {
|
||||||
|
return Ok(format!("(v => {} = v)", g));
|
||||||
|
}
|
||||||
|
_ => bail!("\"no class\" methods must be regular/getter/setter"),
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let op = match &method_data.kind {
|
||||||
|
shared::MethodKind::Constructor => return Ok(format!("new {}", class)),
|
||||||
|
shared::MethodKind::Operation(op) => op,
|
||||||
|
};
|
||||||
|
let target = if import.structural {
|
||||||
|
let location = if op.is_static { &class } else { "this" };
|
||||||
|
|
||||||
|
match &op.kind {
|
||||||
|
shared::OperationKind::Regular => {
|
||||||
|
let nargs = descriptor.unwrap_function().arguments.len();
|
||||||
|
let mut s = format!("function(");
|
||||||
|
for i in 0..nargs - 1 {
|
||||||
|
if i > 0 {
|
||||||
|
drop(write!(s, ", "));
|
||||||
|
}
|
||||||
|
drop(write!(s, "x{}", i));
|
||||||
|
}
|
||||||
|
s.push_str(") { \nreturn this.");
|
||||||
|
s.push_str(&import.function.name);
|
||||||
|
s.push_str("(");
|
||||||
|
for i in 0..nargs - 1 {
|
||||||
|
if i > 0 {
|
||||||
|
drop(write!(s, ", "));
|
||||||
|
}
|
||||||
|
drop(write!(s, "x{}", i));
|
||||||
|
}
|
||||||
|
s.push_str(");\n}");
|
||||||
|
s
|
||||||
|
}
|
||||||
|
shared::OperationKind::Getter(g) => format!(
|
||||||
|
"function() {{
|
||||||
|
return {}.{};
|
||||||
|
}}",
|
||||||
|
location, g
|
||||||
|
),
|
||||||
|
shared::OperationKind::Setter(s) => format!(
|
||||||
|
"function(y) {{
|
||||||
|
{}.{} = y;
|
||||||
|
}}",
|
||||||
|
location, s
|
||||||
|
),
|
||||||
|
shared::OperationKind::IndexingGetter => format!(
|
||||||
|
"function(y) {{
|
||||||
|
return {}[y];
|
||||||
|
}}",
|
||||||
|
location
|
||||||
|
),
|
||||||
|
shared::OperationKind::IndexingSetter => format!(
|
||||||
|
"function(y, z) {{
|
||||||
|
{}[y] = z;
|
||||||
|
}}",
|
||||||
|
location
|
||||||
|
),
|
||||||
|
shared::OperationKind::IndexingDeleter => format!(
|
||||||
|
"function(y) {{
|
||||||
|
delete {}[y];
|
||||||
|
}}",
|
||||||
|
location
|
||||||
|
),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let (location, binding) = if op.is_static {
|
||||||
|
("", format!(".bind({})", class))
|
||||||
|
} else {
|
||||||
|
(".prototype", "".into())
|
||||||
|
};
|
||||||
|
|
||||||
|
match &op.kind {
|
||||||
|
shared::OperationKind::Regular => {
|
||||||
|
format!("{}{}.{}{}", class, location, import.function.name, binding)
|
||||||
|
}
|
||||||
|
shared::OperationKind::Getter(g) => {
|
||||||
|
self.cx.expose_get_inherited_descriptor();
|
||||||
|
format!(
|
||||||
|
"GetOwnOrInheritedPropertyDescriptor({}{}, '{}').get{}",
|
||||||
|
class, location, g, binding,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
shared::OperationKind::Setter(s) => {
|
||||||
|
self.cx.expose_get_inherited_descriptor();
|
||||||
|
format!(
|
||||||
|
"GetOwnOrInheritedPropertyDescriptor({}{}, '{}').set{}",
|
||||||
|
class, location, s, binding,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
shared::OperationKind::IndexingGetter => panic!("indexing getter should be structural"),
|
||||||
|
shared::OperationKind::IndexingSetter => panic!("indexing setter should be structural"),
|
||||||
|
shared::OperationKind::IndexingDeleter => panic!("indexing deleter should be structural"),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let fallback = if import.structural {
|
||||||
|
"".to_string()
|
||||||
|
} else {
|
||||||
|
format!(
|
||||||
|
" || function() {{
|
||||||
|
throw new Error(`wasm-bindgen: {} does not exist`);
|
||||||
|
}}",
|
||||||
|
target
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
self.cx.global(&format!(
|
||||||
|
"const {}_target = {}{};",
|
||||||
|
import.shim, target, fallback
|
||||||
|
));
|
||||||
|
Ok(format!(
|
||||||
|
"{}_target{}",
|
||||||
|
import.shim,
|
||||||
|
if op.is_static { "" } else { ".call" }
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_import_type(
|
fn generate_import_type(
|
||||||
|
@ -514,6 +514,7 @@ impl<'a> ConvertToAst<(BindgenAttrs, &'a Option<String>)> for syn::ForeignItemFn
|
|||||||
|
|
||||||
let shim = {
|
let shim = {
|
||||||
let ns = match kind {
|
let ns = match kind {
|
||||||
|
ast::ImportFunctionKind::ScopedMethod { .. } |
|
||||||
ast::ImportFunctionKind::Normal => (0, "n"),
|
ast::ImportFunctionKind::Normal => (0, "n"),
|
||||||
ast::ImportFunctionKind::Method { ref class, .. } => (1, &class[..]),
|
ast::ImportFunctionKind::Method { ref class, .. } => (1, &class[..]),
|
||||||
};
|
};
|
||||||
|
@ -48,7 +48,7 @@ pub struct ImportFunction {
|
|||||||
|
|
||||||
#[derive(Deserialize, Serialize)]
|
#[derive(Deserialize, Serialize)]
|
||||||
pub struct MethodData {
|
pub struct MethodData {
|
||||||
pub class: String,
|
pub class: Option<String>,
|
||||||
pub kind: MethodKind,
|
pub kind: MethodKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
4
crates/webidl-tests/global.js
Normal file
4
crates/webidl-tests/global.js
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
global.global_no_args = () => 3;
|
||||||
|
global.global_with_args = (a, b) => a + b;
|
||||||
|
global.global_attribute = 'x';
|
||||||
|
|
12
crates/webidl-tests/global.rs
Normal file
12
crates/webidl-tests/global.rs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
use wasm_bindgen_test::*;
|
||||||
|
|
||||||
|
include!(concat!(env!("OUT_DIR"), "/global.rs"));
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn works() {
|
||||||
|
assert_eq!(Global::global_no_args(), 3);
|
||||||
|
assert_eq!(Global::global_with_args("a", "b"), "ab");
|
||||||
|
assert_eq!(Global::global_attribute(), "x");
|
||||||
|
Global::set_global_attribute("y");
|
||||||
|
assert_eq!(Global::global_attribute(), "y");
|
||||||
|
}
|
6
crates/webidl-tests/global.webidl
vendored
Normal file
6
crates/webidl-tests/global.webidl
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
[Global=x]
|
||||||
|
interface Global {
|
||||||
|
unsigned long global_no_args();
|
||||||
|
DOMString global_with_args(DOMString a, DOMString b);
|
||||||
|
attribute DOMString global_attribute;
|
||||||
|
};
|
@ -10,3 +10,4 @@ pub mod namespace;
|
|||||||
pub mod simple;
|
pub mod simple;
|
||||||
pub mod throws;
|
pub mod throws;
|
||||||
pub mod dictionary;
|
pub mod dictionary;
|
||||||
|
pub mod global;
|
||||||
|
@ -87,11 +87,7 @@ global.Unforgeable = class Unforgeable {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
global.GlobalMethod = class GlobalMethod {
|
global.m = () => 123;
|
||||||
constructor() {
|
|
||||||
this.m = () => 123;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
global.Indexing = function () {
|
global.Indexing = function () {
|
||||||
return new Proxy({}, {
|
return new Proxy({}, {
|
||||||
|
@ -64,8 +64,7 @@ fn nullable_method() {
|
|||||||
|
|
||||||
#[wasm_bindgen_test]
|
#[wasm_bindgen_test]
|
||||||
fn global_method() {
|
fn global_method() {
|
||||||
let f = GlobalMethod::new().unwrap();
|
assert_eq!(GlobalMethod::m(), 123);
|
||||||
assert_eq!(f.m(), 123);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[wasm_bindgen_test]
|
#[wasm_bindgen_test]
|
||||||
|
@ -591,6 +591,11 @@ fn member_attribute<'src>(
|
|||||||
|
|
||||||
let is_structural = util::is_structural(attrs);
|
let is_structural = util::is_structural(attrs);
|
||||||
let throws = util::throws(attrs);
|
let throws = util::throws(attrs);
|
||||||
|
let global = first_pass
|
||||||
|
.interfaces
|
||||||
|
.get(self_name)
|
||||||
|
.map(|interface_data| interface_data.global)
|
||||||
|
.unwrap_or(false);
|
||||||
|
|
||||||
for import_function in first_pass.create_getter(
|
for import_function in first_pass.create_getter(
|
||||||
identifier,
|
identifier,
|
||||||
@ -599,6 +604,7 @@ fn member_attribute<'src>(
|
|||||||
is_static,
|
is_static,
|
||||||
is_structural,
|
is_structural,
|
||||||
throws,
|
throws,
|
||||||
|
global,
|
||||||
) {
|
) {
|
||||||
program.imports.push(wrap_import_function(import_function));
|
program.imports.push(wrap_import_function(import_function));
|
||||||
}
|
}
|
||||||
@ -611,6 +617,7 @@ fn member_attribute<'src>(
|
|||||||
is_static,
|
is_static,
|
||||||
is_structural,
|
is_structural,
|
||||||
throws,
|
throws,
|
||||||
|
global,
|
||||||
) {
|
) {
|
||||||
program.imports.push(wrap_import_function(import_function));
|
program.imports.push(wrap_import_function(import_function));
|
||||||
}
|
}
|
||||||
@ -712,6 +719,12 @@ fn member_operation<'src>(
|
|||||||
operation_ids.push(id);
|
operation_ids.push(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let global = first_pass
|
||||||
|
.interfaces
|
||||||
|
.get(self_name)
|
||||||
|
.map(|interface_data| interface_data.global)
|
||||||
|
.unwrap_or(false);
|
||||||
|
|
||||||
for id in operation_ids {
|
for id in operation_ids {
|
||||||
let methods = first_pass
|
let methods = first_pass
|
||||||
.create_basic_method(
|
.create_basic_method(
|
||||||
@ -724,15 +737,10 @@ fn member_operation<'src>(
|
|||||||
OperationId::IndexingGetter |
|
OperationId::IndexingGetter |
|
||||||
OperationId::IndexingSetter |
|
OperationId::IndexingSetter |
|
||||||
OperationId::IndexingDeleter => true,
|
OperationId::IndexingDeleter => true,
|
||||||
_ => {
|
_ => false,
|
||||||
first_pass
|
|
||||||
.interfaces
|
|
||||||
.get(self_name)
|
|
||||||
.map(|interface_data| interface_data.global)
|
|
||||||
.unwrap_or(false)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
util::throws(attrs),
|
util::throws(attrs),
|
||||||
|
global,
|
||||||
);
|
);
|
||||||
|
|
||||||
for method in methods {
|
for method in methods {
|
||||||
|
@ -297,6 +297,7 @@ impl<'src> FirstPassRecord<'src> {
|
|||||||
let rust_name = rust_ident(&rust_name);
|
let rust_name = rust_ident(&rust_name);
|
||||||
let shim = {
|
let shim = {
|
||||||
let ns = match kind {
|
let ns = match kind {
|
||||||
|
backend::ast::ImportFunctionKind::ScopedMethod { .. } |
|
||||||
backend::ast::ImportFunctionKind::Normal => "",
|
backend::ast::ImportFunctionKind::Normal => "",
|
||||||
backend::ast::ImportFunctionKind::Method { ref class, .. } => class,
|
backend::ast::ImportFunctionKind::Method { ref class, .. } => class,
|
||||||
};
|
};
|
||||||
@ -389,6 +390,7 @@ impl<'src> FirstPassRecord<'src> {
|
|||||||
is_static: bool,
|
is_static: bool,
|
||||||
structural: bool,
|
structural: bool,
|
||||||
catch: bool,
|
catch: bool,
|
||||||
|
global: bool,
|
||||||
) -> Vec<backend::ast::ImportFunction> {
|
) -> Vec<backend::ast::ImportFunction> {
|
||||||
let (overloaded, same_argument_names) = self.get_operation_overloading(
|
let (overloaded, same_argument_names) = self.get_operation_overloading(
|
||||||
arguments,
|
arguments,
|
||||||
@ -410,20 +412,26 @@ impl<'src> FirstPassRecord<'src> {
|
|||||||
first_pass::OperationId::IndexingSetter => "set",
|
first_pass::OperationId::IndexingSetter => "set",
|
||||||
first_pass::OperationId::IndexingDeleter => "delete",
|
first_pass::OperationId::IndexingDeleter => "delete",
|
||||||
};
|
};
|
||||||
|
let operation_kind = match &operation_id {
|
||||||
let kind = backend::ast::ImportFunctionKind::Method {
|
first_pass::OperationId::Constructor => panic!("constructors are unsupported"),
|
||||||
class: self_name.to_string(),
|
first_pass::OperationId::Operation(_) => backend::ast::OperationKind::Regular,
|
||||||
ty: ident_ty(rust_ident(camel_case_ident(&self_name).as_str())),
|
first_pass::OperationId::IndexingGetter => backend::ast::OperationKind::IndexingGetter,
|
||||||
kind: backend::ast::MethodKind::Operation(backend::ast::Operation {
|
first_pass::OperationId::IndexingSetter => backend::ast::OperationKind::IndexingSetter,
|
||||||
is_static,
|
first_pass::OperationId::IndexingDeleter => backend::ast::OperationKind::IndexingDeleter,
|
||||||
kind: match &operation_id {
|
};
|
||||||
first_pass::OperationId::Constructor => panic!("constructors are unsupported"),
|
let operation = backend::ast::Operation { is_static, kind: operation_kind };
|
||||||
first_pass::OperationId::Operation(_) => backend::ast::OperationKind::Regular,
|
let ty = ident_ty(rust_ident(camel_case_ident(&self_name).as_str()));
|
||||||
first_pass::OperationId::IndexingGetter => backend::ast::OperationKind::IndexingGetter,
|
let kind = if global {
|
||||||
first_pass::OperationId::IndexingSetter => backend::ast::OperationKind::IndexingSetter,
|
backend::ast::ImportFunctionKind::ScopedMethod {
|
||||||
first_pass::OperationId::IndexingDeleter => backend::ast::OperationKind::IndexingDeleter,
|
ty,
|
||||||
},
|
operation,
|
||||||
}),
|
}
|
||||||
|
} else {
|
||||||
|
backend::ast::ImportFunctionKind::Method {
|
||||||
|
class: self_name.to_string(),
|
||||||
|
ty,
|
||||||
|
kind: backend::ast::MethodKind::Operation(operation),
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let ret = match return_type.to_idl_type(self) {
|
let ret = match return_type.to_idl_type(self) {
|
||||||
@ -591,19 +599,29 @@ impl<'src> FirstPassRecord<'src> {
|
|||||||
is_static: bool,
|
is_static: bool,
|
||||||
is_structural: bool,
|
is_structural: bool,
|
||||||
catch: bool,
|
catch: bool,
|
||||||
|
global: bool,
|
||||||
) -> Vec<backend::ast::ImportFunction> {
|
) -> Vec<backend::ast::ImportFunction> {
|
||||||
let ret = match ty.to_idl_type(self) {
|
let ret = match ty.to_idl_type(self) {
|
||||||
None => return Vec::new(),
|
None => return Vec::new(),
|
||||||
Some(idl_type) => idl_type,
|
Some(idl_type) => idl_type,
|
||||||
};
|
};
|
||||||
|
let operation = backend::ast::Operation {
|
||||||
|
is_static,
|
||||||
|
kind: backend::ast::OperationKind::Getter(Some(raw_ident(name))),
|
||||||
|
};
|
||||||
|
let ty = ident_ty(rust_ident(camel_case_ident(&self_name).as_str()));
|
||||||
|
|
||||||
let kind = backend::ast::ImportFunctionKind::Method {
|
let kind = if global {
|
||||||
class: self_name.to_string(),
|
backend::ast::ImportFunctionKind::ScopedMethod {
|
||||||
ty: ident_ty(rust_ident(camel_case_ident(&self_name).as_str())),
|
ty,
|
||||||
kind: backend::ast::MethodKind::Operation(backend::ast::Operation {
|
operation,
|
||||||
is_static,
|
}
|
||||||
kind: backend::ast::OperationKind::Getter(Some(raw_ident(name))),
|
} else {
|
||||||
}),
|
backend::ast::ImportFunctionKind::Method {
|
||||||
|
class: self_name.to_string(),
|
||||||
|
ty,
|
||||||
|
kind: backend::ast::MethodKind::Operation(operation),
|
||||||
|
}
|
||||||
};
|
};
|
||||||
let doc_comment = Some(format!("The `{}` getter\n\n{}", name, mdn_doc(self_name, Some(name))));
|
let doc_comment = Some(format!("The `{}` getter\n\n{}", name, mdn_doc(self_name, Some(name))));
|
||||||
|
|
||||||
@ -614,19 +632,30 @@ impl<'src> FirstPassRecord<'src> {
|
|||||||
pub fn create_setter(
|
pub fn create_setter(
|
||||||
&self,
|
&self,
|
||||||
name: &str,
|
name: &str,
|
||||||
ty: weedle::types::Type,
|
field_ty: weedle::types::Type,
|
||||||
self_name: &str,
|
self_name: &str,
|
||||||
is_static: bool,
|
is_static: bool,
|
||||||
is_structural: bool,
|
is_structural: bool,
|
||||||
catch: bool,
|
catch: bool,
|
||||||
|
global: bool,
|
||||||
) -> Vec<backend::ast::ImportFunction> {
|
) -> Vec<backend::ast::ImportFunction> {
|
||||||
let kind = backend::ast::ImportFunctionKind::Method {
|
let operation = backend::ast::Operation {
|
||||||
class: self_name.to_string(),
|
is_static,
|
||||||
ty: ident_ty(rust_ident(camel_case_ident(&self_name).as_str())),
|
kind: backend::ast::OperationKind::Setter(Some(raw_ident(name))),
|
||||||
kind: backend::ast::MethodKind::Operation(backend::ast::Operation {
|
};
|
||||||
is_static,
|
let ty = ident_ty(rust_ident(camel_case_ident(&self_name).as_str()));
|
||||||
kind: backend::ast::OperationKind::Setter(Some(raw_ident(name))),
|
|
||||||
}),
|
let kind = if global {
|
||||||
|
backend::ast::ImportFunctionKind::ScopedMethod {
|
||||||
|
ty,
|
||||||
|
operation,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
backend::ast::ImportFunctionKind::Method {
|
||||||
|
class: self_name.to_string(),
|
||||||
|
ty,
|
||||||
|
kind: backend::ast::MethodKind::Operation(operation),
|
||||||
|
}
|
||||||
};
|
};
|
||||||
let doc_comment = Some(format!("The `{}` setter\n\n{}", name, mdn_doc(self_name, Some(name))));
|
let doc_comment = Some(format!("The `{}` setter\n\n{}", name, mdn_doc(self_name, Some(name))));
|
||||||
|
|
||||||
@ -636,7 +665,7 @@ impl<'src> FirstPassRecord<'src> {
|
|||||||
false,
|
false,
|
||||||
&[(
|
&[(
|
||||||
name,
|
name,
|
||||||
match ty.to_idl_type(self) {
|
match field_ty.to_idl_type(self) {
|
||||||
None => return Vec::new(),
|
None => return Vec::new(),
|
||||||
Some(idl_type) => idl_type,
|
Some(idl_type) => idl_type,
|
||||||
},
|
},
|
||||||
|
@ -6,13 +6,9 @@ use std::f64;
|
|||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
use wasm_bindgen::JsCast;
|
use wasm_bindgen::JsCast;
|
||||||
|
|
||||||
#[wasm_bindgen]
|
|
||||||
extern "C" {
|
|
||||||
static document: web_sys::Document;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
pub fn draw() {
|
pub fn draw() {
|
||||||
|
let document = web_sys::Window::document().unwrap();
|
||||||
let canvas = document.get_element_by_id("canvas").unwrap();
|
let canvas = document.get_element_by_id("canvas").unwrap();
|
||||||
let canvas: web_sys::HtmlCanvasElement = canvas
|
let canvas: web_sys::HtmlCanvasElement = canvas
|
||||||
.dyn_into::<web_sys::HtmlCanvasElement>()
|
.dyn_into::<web_sys::HtmlCanvasElement>()
|
||||||
|
@ -40,11 +40,6 @@ pub struct Signature {
|
|||||||
pub email: String,
|
pub email: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[wasm_bindgen]
|
|
||||||
extern "C" {
|
|
||||||
static window: Window;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
pub fn run() -> Promise {
|
pub fn run() -> Promise {
|
||||||
let mut request_options = RequestInit::new();
|
let mut request_options = RequestInit::new();
|
||||||
@ -56,7 +51,7 @@ pub fn run() -> Promise {
|
|||||||
// the RequestInit struct will eventually support setting headers, but that's missing right now
|
// the RequestInit struct will eventually support setting headers, but that's missing right now
|
||||||
req.headers().set("Accept", "application/vnd.github.v3+json").unwrap();
|
req.headers().set("Accept", "application/vnd.github.v3+json").unwrap();
|
||||||
|
|
||||||
let req_promise = window.fetch_with_request(&req);
|
let req_promise = Window::fetch_with_request(&req);
|
||||||
|
|
||||||
let to_return = JsFuture::from(req_promise).and_then(|resp_value| {
|
let to_return = JsFuture::from(req_promise).and_then(|resp_value| {
|
||||||
// resp_value is a Response object
|
// resp_value is a Response object
|
||||||
|
Loading…
x
Reference in New Issue
Block a user