mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-03-31 17:31:06 +00:00
Merge remote-tracking branch 'upstream/master' into add-allow-clippy
This commit is contained in:
commit
1b764103f6
crates
cli-support
cli
futures/tests
gc
test/src/rt
threads-xform
wasm-interpreter
web-sys/tests/wasm
webidl-tests
webidl/src
tests
@ -13,7 +13,7 @@ Shared support for the wasm-bindgen-cli package, an internal dependency
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
base64 = "0.9"
|
base64 = "0.9"
|
||||||
failure = "0.1.2"
|
failure = "0.1.2"
|
||||||
parity-wasm = "0.35"
|
parity-wasm = "0.36"
|
||||||
tempfile = "3.0"
|
tempfile = "3.0"
|
||||||
wasm-bindgen-gc = { path = '../gc', version = '=0.2.33' }
|
wasm-bindgen-gc = { path = '../gc', version = '=0.2.33' }
|
||||||
wasm-bindgen-shared = { path = "../shared", version = '=0.2.33' }
|
wasm-bindgen-shared = { path = "../shared", version = '=0.2.33' }
|
||||||
|
@ -1546,6 +1546,23 @@ impl<'a> Context<'a> {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn expose_handle_error(&mut self) {
|
||||||
|
if !self.should_write_global("handle_error") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self.expose_uint32_memory();
|
||||||
|
self.expose_add_heap_object();
|
||||||
|
self.global(
|
||||||
|
"
|
||||||
|
function handleError(exnptr, e) {
|
||||||
|
const view = getUint32Memory();
|
||||||
|
view[exnptr / 4] = 1;
|
||||||
|
view[exnptr / 4 + 1] = addHeapObject(e);
|
||||||
|
}
|
||||||
|
",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
fn wasm_import_needed(&self, name: &str) -> bool {
|
fn wasm_import_needed(&self, name: &str) -> bool {
|
||||||
let imports = match self.module.import_section() {
|
let imports = match self.module.import_section() {
|
||||||
Some(s) => s,
|
Some(s) => s,
|
||||||
|
@ -643,23 +643,16 @@ impl<'a, 'b> Rust2Js<'a, 'b> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if self.catch {
|
if self.catch {
|
||||||
self.cx.expose_uint32_memory();
|
self.cx.expose_handle_error();
|
||||||
self.cx.expose_add_heap_object();
|
|
||||||
let catch = "\
|
|
||||||
const view = getUint32Memory();\n\
|
|
||||||
view[exnptr / 4] = 1;\n\
|
|
||||||
view[exnptr / 4 + 1] = addHeapObject(e);\n\
|
|
||||||
";
|
|
||||||
|
|
||||||
invoc = format!(
|
invoc = format!(
|
||||||
"\
|
"\
|
||||||
try {{\n\
|
try {{\n\
|
||||||
{}
|
{}
|
||||||
}} catch (e) {{\n\
|
}} catch (e) {{\n\
|
||||||
{}
|
handleError(exnptr, e);\n\
|
||||||
}}\
|
}}\
|
||||||
",
|
",
|
||||||
&invoc, catch
|
&invoc
|
||||||
);
|
);
|
||||||
} else if self.catch_and_rethrow {
|
} else if self.catch_and_rethrow {
|
||||||
invoc = format!(
|
invoc = format!(
|
||||||
|
@ -18,7 +18,7 @@ docopt = "1.0"
|
|||||||
env_logger = "0.6"
|
env_logger = "0.6"
|
||||||
failure = "0.1.2"
|
failure = "0.1.2"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
parity-wasm = "0.35"
|
parity-wasm = "0.36"
|
||||||
rouille = { version = "3.0.0", default-features = false }
|
rouille = { version = "3.0.0", default-features = false }
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
serde_derive = "1.0"
|
serde_derive = "1.0"
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
const orig = id => (...args) => {
|
const orig = id => (...args) => {
|
||||||
const logs = document.getElementById(id);
|
const logs = document.getElementById(id);
|
||||||
for (let msg of args) {
|
for (let msg of args) {
|
||||||
logs.innerHTML += `${msg}\n`;
|
logs.textContent += `${msg}\n`;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ pub fn spawn(
|
|||||||
// Now that we've gotten to the point where JS is executing, update our
|
// Now that we've gotten to the point where JS is executing, update our
|
||||||
// status text as at this point we should be asynchronously fetching the
|
// status text as at this point we should be asynchronously fetching the
|
||||||
// wasm module.
|
// wasm module.
|
||||||
document.getElementById('output').innerHTML = "Loading wasm module...";
|
document.getElementById('output').textContent = "Loading wasm module...";
|
||||||
|
|
||||||
async function main(test) {{
|
async function main(test) {{
|
||||||
// this is a facet of using wasm2es6js, a hack until browsers have
|
// this is a facet of using wasm2es6js, a hack until browsers have
|
||||||
|
7
crates/futures/tests/tests.rs
Normal file → Executable file
7
crates/futures/tests/tests.rs
Normal file → Executable file
@ -108,3 +108,10 @@ fn spawn_local_err_no_exception() -> impl Future<Item = (), Error = JsValue> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen_test(async)]
|
||||||
|
fn can_create_multiple_futures_from_same_promise() -> impl Future<Item = (), Error = JsValue> {
|
||||||
|
let promise = js_sys::Promise::resolve(&JsValue::null());
|
||||||
|
let a = JsFuture::from(promise.clone());
|
||||||
|
let b = JsFuture::from(promise);
|
||||||
|
futures::future::join_all(vec![a, b]).map(|_| ())
|
||||||
|
}
|
||||||
|
@ -11,7 +11,7 @@ Support for removing unused items from a wasm executable
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
parity-wasm = "0.35.1"
|
parity-wasm = "0.36"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
rustc-demangle = "0.1.9"
|
rustc-demangle = "0.1.9"
|
||||||
|
|
||||||
|
@ -99,6 +99,10 @@ fn run(config: &mut Config, module: &mut Module) {
|
|||||||
info!("skipping reloc section");
|
info!("skipping reloc section");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
Section::DataCount(..) => {
|
||||||
|
info!("skipping data count section");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
Section::Type(ref mut s) => cx.remap_type_section(s),
|
Section::Type(ref mut s) => cx.remap_type_section(s),
|
||||||
Section::Import(ref mut s) => cx.remap_import_section(s),
|
Section::Import(ref mut s) => cx.remap_import_section(s),
|
||||||
Section::Function(ref mut s) => cx.remap_function_section(s),
|
Section::Function(ref mut s) => cx.remap_function_section(s),
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
(module
|
|
||||||
(memory 0 10)
|
|
||||||
|
|
||||||
(func $foo
|
|
||||||
i32.const 0
|
|
||||||
i32.const 0
|
|
||||||
i32.const 0
|
|
||||||
memory.init 0
|
|
||||||
)
|
|
||||||
|
|
||||||
(data passive "wut")
|
|
||||||
|
|
||||||
)
|
|
||||||
|
|
||||||
;; STDOUT (update this section with `BLESS_TESTS=1` while running tests)
|
|
||||||
;; (module
|
|
||||||
;; (memory (;0;) 0 10))
|
|
||||||
;; STDOUT
|
|
@ -1,29 +0,0 @@
|
|||||||
(module
|
|
||||||
(memory 0 10)
|
|
||||||
|
|
||||||
(func $foo
|
|
||||||
i32.const 0
|
|
||||||
i32.const 0
|
|
||||||
i32.const 0
|
|
||||||
memory.init 1
|
|
||||||
)
|
|
||||||
|
|
||||||
(data passive "wut")
|
|
||||||
(data passive "wut2")
|
|
||||||
(data passive "wut3")
|
|
||||||
|
|
||||||
(start $foo)
|
|
||||||
)
|
|
||||||
|
|
||||||
;; STDOUT (update this section with `BLESS_TESTS=1` while running tests)
|
|
||||||
;; (module
|
|
||||||
;; (type (;0;) (func))
|
|
||||||
;; (func $foo (type 0)
|
|
||||||
;; i32.const 0
|
|
||||||
;; i32.const 0
|
|
||||||
;; i32.const 0
|
|
||||||
;; memory.init 0)
|
|
||||||
;; (memory (;0;) 0 10)
|
|
||||||
;; (start 0)
|
|
||||||
;; (data (;0;) passive "wut2"))
|
|
||||||
;; STDOUT
|
|
@ -1,32 +0,0 @@
|
|||||||
(module
|
|
||||||
(import "" "" (table 0 1 anyfunc))
|
|
||||||
|
|
||||||
(func $foo
|
|
||||||
i32.const 0
|
|
||||||
i32.const 0
|
|
||||||
i32.const 0
|
|
||||||
table.init 1
|
|
||||||
)
|
|
||||||
|
|
||||||
(func $bar)
|
|
||||||
(func $bar2)
|
|
||||||
|
|
||||||
(elem passive $bar)
|
|
||||||
(elem passive $bar2)
|
|
||||||
|
|
||||||
(start $foo)
|
|
||||||
)
|
|
||||||
|
|
||||||
;; STDOUT (update this section with `BLESS_TESTS=1` while running tests)
|
|
||||||
;; (module
|
|
||||||
;; (type (;0;) (func))
|
|
||||||
;; (import "" "" (table (;0;) 0 1 anyfunc))
|
|
||||||
;; (func $foo (type 0)
|
|
||||||
;; i32.const 0
|
|
||||||
;; i32.const 0
|
|
||||||
;; i32.const 0
|
|
||||||
;; table.init 0)
|
|
||||||
;; (func $bar2 (type 0))
|
|
||||||
;; (start 0)
|
|
||||||
;; (elem (;0;) passive $bar2))
|
|
||||||
;; STDOUT
|
|
@ -22,10 +22,10 @@ extern "C" {
|
|||||||
fn getElementById(this: &HTMLDocument, id: &str) -> Element;
|
fn getElementById(this: &HTMLDocument, id: &str) -> Element;
|
||||||
|
|
||||||
type Element;
|
type Element;
|
||||||
#[wasm_bindgen(method, getter = innerHTML, structural)]
|
#[wasm_bindgen(method, getter = textContent, structural)]
|
||||||
fn inner_html(this: &Element) -> String;
|
fn text_content(this: &Element) -> String;
|
||||||
#[wasm_bindgen(method, setter = innerHTML, structural)]
|
#[wasm_bindgen(method, setter = textContent, structural)]
|
||||||
fn set_inner_html(this: &Element, html: &str);
|
fn set_text_content(this: &Element, text: &str);
|
||||||
|
|
||||||
type BrowserError;
|
type BrowserError;
|
||||||
#[wasm_bindgen(method, getter, structural)]
|
#[wasm_bindgen(method, getter, structural)]
|
||||||
@ -37,24 +37,16 @@ impl Browser {
|
|||||||
/// (requires `Node::new()` to have return `None` first).
|
/// (requires `Node::new()` to have return `None` first).
|
||||||
pub fn new() -> Browser {
|
pub fn new() -> Browser {
|
||||||
let pre = document.getElementById("output");
|
let pre = document.getElementById("output");
|
||||||
pre.set_inner_html("");
|
pre.set_text_content("");
|
||||||
Browser { pre }
|
Browser { pre }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl super::Formatter for Browser {
|
impl super::Formatter for Browser {
|
||||||
fn writeln(&self, line: &str) {
|
fn writeln(&self, line: &str) {
|
||||||
let mut html = self.pre.inner_html();
|
let mut html = self.pre.text_content();
|
||||||
for c in line.chars() {
|
html.extend(line.chars().chain(Some('\n')));
|
||||||
match c {
|
self.pre.set_text_content(&html);
|
||||||
'<' => html.push_str("<"),
|
|
||||||
'>' => html.push_str(">"),
|
|
||||||
'&' => html.push_str("&"),
|
|
||||||
c => html.push(c),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
html.push_str("\n");
|
|
||||||
self.pre.set_inner_html(&html);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn log_test(&self, name: &str, result: &Result<(), JsValue>) {
|
fn log_test(&self, name: &str, result: &Result<(), JsValue>) {
|
||||||
|
@ -11,5 +11,5 @@ Support for threading-related transformations in wasm-bindgen
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
parity-wasm = "0.35"
|
parity-wasm = "0.36"
|
||||||
failure = "0.1"
|
failure = "0.1"
|
||||||
|
@ -11,7 +11,7 @@ Micro-interpreter optimized for wasm-bindgen's use case
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
parity-wasm = "0.35"
|
parity-wasm = "0.36"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tempfile = "3"
|
tempfile = "3"
|
||||||
|
@ -151,6 +151,11 @@ export function new_title() {
|
|||||||
return document.createElement("title");
|
return document.createElement("title");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function new_webgl_rendering_context() {
|
||||||
|
const canvas = document.createElement('canvas');
|
||||||
|
return canvas.getContext('webgl');
|
||||||
|
}
|
||||||
|
|
||||||
export function new_xpath_result() {
|
export function new_xpath_result() {
|
||||||
let xmlDoc = new DOMParser().parseFromString("<root><value>tomato</value></root>", "application/xml");
|
let xmlDoc = new DOMParser().parseFromString("<root><value>tomato</value></root>", "application/xml");
|
||||||
let xpathResult = xmlDoc.evaluate("/root//value", xmlDoc, null, XPathResult.ANY_TYPE, null);
|
let xpathResult = xmlDoc.evaluate("/root//value", xmlDoc, null, XPathResult.ANY_TYPE, null);
|
||||||
|
@ -56,6 +56,7 @@ pub mod style_element;
|
|||||||
pub mod table_element;
|
pub mod table_element;
|
||||||
pub mod title_element;
|
pub mod title_element;
|
||||||
pub mod xpath_result;
|
pub mod xpath_result;
|
||||||
|
pub mod whitelisted_immutable_slices;
|
||||||
|
|
||||||
#[wasm_bindgen_test]
|
#[wasm_bindgen_test]
|
||||||
fn deref_works() {
|
fn deref_works() {
|
||||||
|
57
crates/web-sys/tests/wasm/whitelisted_immutable_slices.rs
Normal file
57
crates/web-sys/tests/wasm/whitelisted_immutable_slices.rs
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
//! When generating our web_sys APIs we default to setting slice references that
|
||||||
|
//! get passed to JS as mutable in case they get mutated in JS.
|
||||||
|
//!
|
||||||
|
//! In certain cases we know for sure that the slice will not get mutated - for
|
||||||
|
//! example when working with the WebGlRenderingContext APIs.
|
||||||
|
//!
|
||||||
|
//! These tests ensure that whitelisted methods do indeed accept mutable slices.
|
||||||
|
//! Especially important since this whitelist is stringly typed and currently
|
||||||
|
//! maintained by hand.
|
||||||
|
//!
|
||||||
|
//! @see https://github.com/rustwasm/wasm-bindgen/issues/1005
|
||||||
|
|
||||||
|
use wasm_bindgen::prelude::*;
|
||||||
|
use wasm_bindgen_test::*;
|
||||||
|
use web_sys::WebGlRenderingContext;
|
||||||
|
|
||||||
|
#[wasm_bindgen(module = "./tests/wasm/element.js")]
|
||||||
|
extern "C" {
|
||||||
|
fn new_webgl_rendering_context() -> WebGlRenderingContext;
|
||||||
|
// TODO: Add a function to create another type to test here.
|
||||||
|
// These functions come from element.js
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Uncomment WebGlRenderingContext test. Every now and then we can check if this works
|
||||||
|
// in the latest geckodriver.
|
||||||
|
//
|
||||||
|
// Currently commented out because WebGl isn't working in geckodriver.
|
||||||
|
//
|
||||||
|
// It currently works in chromedriver so if you need to run this in the meantime you can
|
||||||
|
// uncomment this block and run it in using chromedriver.
|
||||||
|
//
|
||||||
|
// CHROMEDRIVER=chromedriver cargo test --manifest-path crates/web-sys/Cargo.toml --target wasm32-unknown-unknown --all-features test_webgl_rendering_context_immutable_slices
|
||||||
|
|
||||||
|
// Ensure that our whitelisted WebGlRenderingContext methods work
|
||||||
|
//#[wasm_bindgen_test]
|
||||||
|
//fn test_webgl_rendering_context_immutable_slices() {
|
||||||
|
// let gl = new_webgl_rendering_context();
|
||||||
|
//
|
||||||
|
// gl.vertex_attrib1fv_with_f32_array(0, &[1.]);
|
||||||
|
// gl.vertex_attrib2fv_with_f32_array(0, &[1.]);
|
||||||
|
// gl.vertex_attrib3fv_with_f32_array(0, &[1.]);
|
||||||
|
// gl.vertex_attrib4fv_with_f32_array(0, &[1.]);
|
||||||
|
//
|
||||||
|
// gl.uniform1fv_with_f32_array(None, &[1.]);
|
||||||
|
// gl.uniform2fv_with_f32_array(None, &[1.]);
|
||||||
|
// gl.uniform3fv_with_f32_array(None, &[1.]);
|
||||||
|
// gl.uniform4fv_with_f32_array(None, &[1.]);
|
||||||
|
//
|
||||||
|
// gl.uniform_matrix2fv_with_f32_array(None, false, &[1.]);
|
||||||
|
// gl.uniform_matrix3fv_with_f32_array(None, false, &[1.]);
|
||||||
|
// gl.uniform_matrix4fv_with_f32_array(None, false, &[1.]);
|
||||||
|
//}
|
||||||
|
|
||||||
|
// TODO:
|
||||||
|
//#[wasm_bindgen_test]
|
||||||
|
//fn test_another_types_immutable_slices_here() {
|
||||||
|
//}
|
@ -1 +1 @@
|
|||||||
// intentionally left blank
|
// Intentionally left blank in order for Cargo to work
|
||||||
|
@ -37,6 +37,7 @@ pub(crate) struct FirstPassRecord<'src> {
|
|||||||
pub(crate) dictionaries: BTreeMap<&'src str, DictionaryData<'src>>,
|
pub(crate) dictionaries: BTreeMap<&'src str, DictionaryData<'src>>,
|
||||||
pub(crate) callbacks: BTreeSet<&'src str>,
|
pub(crate) callbacks: BTreeSet<&'src str>,
|
||||||
pub(crate) callback_interfaces: BTreeMap<&'src str, CallbackInterfaceData<'src>>,
|
pub(crate) callback_interfaces: BTreeMap<&'src str, CallbackInterfaceData<'src>>,
|
||||||
|
pub(crate) immutable_f32_whitelist: BTreeSet<&'static str>
|
||||||
}
|
}
|
||||||
|
|
||||||
/// We need to collect interface data during the first pass, to be used later.
|
/// We need to collect interface data during the first pass, to be used later.
|
||||||
@ -83,6 +84,9 @@ pub(crate) struct CallbackInterfaceData<'src> {
|
|||||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy)]
|
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy)]
|
||||||
pub(crate) enum OperationId<'src> {
|
pub(crate) enum OperationId<'src> {
|
||||||
Constructor(IgnoreTraits<&'src str>),
|
Constructor(IgnoreTraits<&'src str>),
|
||||||
|
/// The name of a function in crates/web-sys/webidls/enabled/*.webidl
|
||||||
|
///
|
||||||
|
/// ex: Operation(Some("vertexAttrib1fv"))
|
||||||
Operation(Option<&'src str>),
|
Operation(Option<&'src str>),
|
||||||
IndexingGetter,
|
IndexingGetter,
|
||||||
IndexingSetter,
|
IndexingSetter,
|
||||||
|
@ -41,7 +41,10 @@ pub(crate) enum IdlType<'a> {
|
|||||||
Uint16Array,
|
Uint16Array,
|
||||||
Int32Array,
|
Int32Array,
|
||||||
Uint32Array,
|
Uint32Array,
|
||||||
Float32Array,
|
Float32Array {
|
||||||
|
/// Whether or not the generated web-sys function should use an immutable slice
|
||||||
|
immutable: bool
|
||||||
|
},
|
||||||
Float64Array,
|
Float64Array,
|
||||||
ArrayBufferView,
|
ArrayBufferView,
|
||||||
BufferSource,
|
BufferSource,
|
||||||
@ -324,6 +327,15 @@ impl<'a> ToIdlType<'a> for Identifier<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We default to Float32Array's being mutable, but in certain cases where we're certain that
|
||||||
|
// slices won't get mutated on the JS side (such as the WebGL APIs) we might, later in the flow,
|
||||||
|
// instead use the immutable version.
|
||||||
|
impl<'a> ToIdlType<'a> for term::Float32Array {
|
||||||
|
fn to_idl_type(&self, _record: &FirstPassRecord<'a>) -> IdlType<'a> {
|
||||||
|
IdlType::Float32Array {immutable: false}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! terms_to_idl_type {
|
macro_rules! terms_to_idl_type {
|
||||||
($($t:tt => $r:tt)*) => ($(
|
($($t:tt => $r:tt)*) => ($(
|
||||||
impl<'a> ToIdlType<'a> for term::$t {
|
impl<'a> ToIdlType<'a> for term::$t {
|
||||||
@ -331,7 +343,7 @@ macro_rules! terms_to_idl_type {
|
|||||||
IdlType::$r
|
IdlType::$r
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)*)
|
)*);
|
||||||
}
|
}
|
||||||
|
|
||||||
terms_to_idl_type! {
|
terms_to_idl_type! {
|
||||||
@ -358,7 +370,6 @@ terms_to_idl_type! {
|
|||||||
Uint16Array => Uint16Array
|
Uint16Array => Uint16Array
|
||||||
Uint32Array => Uint32Array
|
Uint32Array => Uint32Array
|
||||||
Uint8ClampedArray => Uint8ClampedArray
|
Uint8ClampedArray => Uint8ClampedArray
|
||||||
Float32Array => Float32Array
|
|
||||||
Float64Array => Float64Array
|
Float64Array => Float64Array
|
||||||
ArrayBufferView => ArrayBufferView
|
ArrayBufferView => ArrayBufferView
|
||||||
BufferSource => BufferSource
|
BufferSource => BufferSource
|
||||||
@ -396,7 +407,7 @@ impl<'a> IdlType<'a> {
|
|||||||
IdlType::Uint16Array => dst.push_str("u16_array"),
|
IdlType::Uint16Array => dst.push_str("u16_array"),
|
||||||
IdlType::Int32Array => dst.push_str("i32_array"),
|
IdlType::Int32Array => dst.push_str("i32_array"),
|
||||||
IdlType::Uint32Array => dst.push_str("u32_array"),
|
IdlType::Uint32Array => dst.push_str("u32_array"),
|
||||||
IdlType::Float32Array => dst.push_str("f32_array"),
|
IdlType::Float32Array { .. } => dst.push_str("f32_array"),
|
||||||
IdlType::Float64Array => dst.push_str("f64_array"),
|
IdlType::Float64Array => dst.push_str("f64_array"),
|
||||||
IdlType::ArrayBufferView => dst.push_str("array_buffer_view"),
|
IdlType::ArrayBufferView => dst.push_str("array_buffer_view"),
|
||||||
IdlType::BufferSource => dst.push_str("buffer_source"),
|
IdlType::BufferSource => dst.push_str("buffer_source"),
|
||||||
@ -501,16 +512,16 @@ impl<'a> IdlType<'a> {
|
|||||||
|
|
||||||
IdlType::ArrayBuffer => js_sys("ArrayBuffer"),
|
IdlType::ArrayBuffer => js_sys("ArrayBuffer"),
|
||||||
IdlType::DataView => None,
|
IdlType::DataView => None,
|
||||||
IdlType::Int8Array => Some(array("i8", pos)),
|
IdlType::Int8Array => Some(array("i8", pos, false)),
|
||||||
IdlType::Uint8Array => Some(array("u8", pos)),
|
IdlType::Uint8Array => Some(array("u8", pos, false)),
|
||||||
IdlType::Uint8ArrayMut => Some(array("u8", pos)),
|
IdlType::Uint8ArrayMut => Some(array("u8", pos, false)),
|
||||||
IdlType::Uint8ClampedArray => Some(clamped(array("u8", pos))),
|
IdlType::Uint8ClampedArray => Some(clamped(array("u8", pos, false))),
|
||||||
IdlType::Int16Array => Some(array("i16", pos)),
|
IdlType::Int16Array => Some(array("i16", pos, false)),
|
||||||
IdlType::Uint16Array => Some(array("u16", pos)),
|
IdlType::Uint16Array => Some(array("u16", pos, false)),
|
||||||
IdlType::Int32Array => Some(array("i32", pos)),
|
IdlType::Int32Array => Some(array("i32", pos, false)),
|
||||||
IdlType::Uint32Array => Some(array("u32", pos)),
|
IdlType::Uint32Array => Some(array("u32", pos, false)),
|
||||||
IdlType::Float32Array => Some(array("f32", pos)),
|
IdlType::Float32Array {immutable} => Some(array("f32", pos, *immutable)),
|
||||||
IdlType::Float64Array => Some(array("f64", pos)),
|
IdlType::Float64Array => Some(array("f64", pos, false)),
|
||||||
|
|
||||||
IdlType::ArrayBufferView | IdlType::BufferSource => js_sys("Object"),
|
IdlType::ArrayBufferView | IdlType::BufferSource => js_sys("Object"),
|
||||||
IdlType::Interface(name)
|
IdlType::Interface(name)
|
||||||
|
@ -82,6 +82,8 @@ fn parse(webidl_source: &str, allowed_types: Option<&[&str]>) -> Result<Program>
|
|||||||
|
|
||||||
let mut first_pass_record: FirstPassRecord = Default::default();
|
let mut first_pass_record: FirstPassRecord = Default::default();
|
||||||
first_pass_record.builtin_idents = builtin_idents();
|
first_pass_record.builtin_idents = builtin_idents();
|
||||||
|
first_pass_record.immutable_f32_whitelist = immutable_f32_whitelist();
|
||||||
|
|
||||||
definitions.first_pass(&mut first_pass_record, ())?;
|
definitions.first_pass(&mut first_pass_record, ())?;
|
||||||
let mut program = Default::default();
|
let mut program = Default::default();
|
||||||
let mut submodules = Vec::new();
|
let mut submodules = Vec::new();
|
||||||
@ -179,6 +181,26 @@ fn builtin_idents() -> BTreeSet<Ident> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn immutable_f32_whitelist() -> BTreeSet<&'static str> {
|
||||||
|
BTreeSet::from_iter(
|
||||||
|
vec![
|
||||||
|
// WebGlRenderingContext
|
||||||
|
"uniform1fv",
|
||||||
|
"uniform2fv",
|
||||||
|
"uniform3fv",
|
||||||
|
"uniform4fv",
|
||||||
|
"uniformMatrix2fv",
|
||||||
|
"uniformMatrix3fv",
|
||||||
|
"uniformMatrix4fv",
|
||||||
|
"vertexAttrib1fv",
|
||||||
|
"vertexAttrib2fv",
|
||||||
|
"vertexAttrib3fv",
|
||||||
|
"vertexAttrib4fv",
|
||||||
|
// TODO: Add another type's functions here. Leave a comment header with the type name
|
||||||
|
]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/// Run codegen on the AST to generate rust code.
|
/// Run codegen on the AST to generate rust code.
|
||||||
fn compile_ast(mut ast: Program) -> String {
|
fn compile_ast(mut ast: Program) -> String {
|
||||||
// Iteratively prune all entries from the AST which reference undefined
|
// Iteratively prune all entries from the AST which reference undefined
|
||||||
|
@ -67,13 +67,13 @@ pub fn mdn_doc(class: &str, method: Option<&str>) -> String {
|
|||||||
format!("[MDN Documentation]({})", link).into()
|
format!("[MDN Documentation]({})", link).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Array type is borrowed for arguments (`&[T]`) and owned for return value (`Vec<T>`).
|
// Array type is borrowed for arguments (`&mut [T]` or `&[T]`) and owned for return value (`Vec<T>`).
|
||||||
pub(crate) fn array(base_ty: &str, pos: TypePosition) -> syn::Type {
|
pub(crate) fn array(base_ty: &str, pos: TypePosition, immutable: bool) -> syn::Type {
|
||||||
match pos {
|
match pos {
|
||||||
TypePosition::Argument => {
|
TypePosition::Argument => {
|
||||||
shared_ref(
|
shared_ref(
|
||||||
slice_ty(ident_ty(raw_ident(base_ty))),
|
slice_ty(ident_ty(raw_ident(base_ty))),
|
||||||
/*mutable =*/ true,
|
/*mutable =*/ !immutable,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
TypePosition::Return => vec_ty(ident_ty(raw_ident(base_ty))),
|
TypePosition::Return => vec_ty(ident_ty(raw_ident(base_ty))),
|
||||||
@ -433,7 +433,10 @@ impl<'src> FirstPassRecord<'src> {
|
|||||||
);
|
);
|
||||||
signatures.push((signature, idl_args.clone()));
|
signatures.push((signature, idl_args.clone()));
|
||||||
}
|
}
|
||||||
idl_args.push(arg.ty.to_idl_type(self));
|
|
||||||
|
let mut idl_type = arg.ty.to_idl_type(self);
|
||||||
|
let idl_type = self.maybe_adjust(idl_type, id);
|
||||||
|
idl_args.push(idl_type);
|
||||||
}
|
}
|
||||||
signatures.push((signature, idl_args));
|
signatures.push((signature, idl_args));
|
||||||
}
|
}
|
||||||
@ -627,6 +630,34 @@ impl<'src> FirstPassRecord<'src> {
|
|||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// When generating our web_sys APIs we default to setting slice references that
|
||||||
|
/// get passed to JS as mutable in case they get mutated in JS.
|
||||||
|
///
|
||||||
|
/// In certain cases we know for sure that the slice will not get mutated - for
|
||||||
|
/// example when working with the WebGlRenderingContext APIs.
|
||||||
|
///
|
||||||
|
/// Here we implement a whitelist for those cases. This whitelist is currently
|
||||||
|
/// maintained by hand.
|
||||||
|
///
|
||||||
|
/// When adding to this whitelist add tests to crates/web-sys/tests/wasm/whitelisted_immutable_slices.rs
|
||||||
|
fn maybe_adjust<'a>(&self, mut idl_type: IdlType<'a>, id: &'a OperationId) -> IdlType<'a> {
|
||||||
|
let op = match id {
|
||||||
|
OperationId::Operation(Some(op)) => op,
|
||||||
|
_ => return idl_type
|
||||||
|
};
|
||||||
|
|
||||||
|
if self.immutable_f32_whitelist.contains(op) {
|
||||||
|
flag_slices_immutable(&mut idl_type)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Add other whitelisted slices here, such as F64 or u8..
|
||||||
|
|
||||||
|
idl_type
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Search for an attribute by name in some webidl object's attributes.
|
/// Search for an attribute by name in some webidl object's attributes.
|
||||||
@ -707,3 +738,22 @@ pub fn public() -> syn::Visibility {
|
|||||||
pub_token: Default::default(),
|
pub_token: Default::default(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn flag_slices_immutable(ty: &mut IdlType) {
|
||||||
|
match ty {
|
||||||
|
IdlType::Float32Array { immutable } => *immutable = true,
|
||||||
|
IdlType::Nullable(item) => flag_slices_immutable(item),
|
||||||
|
IdlType::FrozenArray(item) => flag_slices_immutable(item),
|
||||||
|
IdlType::Sequence(item) => flag_slices_immutable(item),
|
||||||
|
IdlType::Promise(item) => flag_slices_immutable(item),
|
||||||
|
IdlType::Record(item1, item2) => {
|
||||||
|
flag_slices_immutable(item1);
|
||||||
|
flag_slices_immutable(item2);
|
||||||
|
},
|
||||||
|
IdlType::Union(list) => {
|
||||||
|
for item in list { flag_slices_immutable(item); }
|
||||||
|
}
|
||||||
|
// catch-all for everything else like Object
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
11
tests/headless.rs
Normal file → Executable file
11
tests/headless.rs
Normal file → Executable file
@ -26,3 +26,14 @@ impl ConsumeRetString {
|
|||||||
fn works() {
|
fn works() {
|
||||||
ConsumeRetString.consume();
|
ConsumeRetString.consume();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
extern {
|
||||||
|
#[wasm_bindgen(js_namespace = console)]
|
||||||
|
pub fn log(s: &str);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn can_log_html_strings() {
|
||||||
|
log("<script>alert('lol')</script>");
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user