diff --git a/crates/web-sys/tests/wasm/whitelisted_immutable_slices.rs b/crates/web-sys/tests/wasm/whitelisted_immutable_slices.rs index 453e9822..ea8286f5 100644 --- a/crates/web-sys/tests/wasm/whitelisted_immutable_slices.rs +++ b/crates/web-sys/tests/wasm/whitelisted_immutable_slices.rs @@ -26,7 +26,7 @@ extern "C" { // 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 test_webgl_rendering_context_immutable_slices +// 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] diff --git a/crates/webidl/Cargo.toml b/crates/webidl/Cargo.toml index b3e3de32..c5c747ac 100644 --- a/crates/webidl/Cargo.toml +++ b/crates/webidl/Cargo.toml @@ -14,6 +14,7 @@ Support for parsing WebIDL specific to wasm-bindgen [dependencies] failure = "0.1.2" heck = "0.3" +lazy_static = "1.2.0" log = "0.4.1" proc-macro2 = "0.4.8" quote = '0.6' diff --git a/crates/webidl/src/lib.rs b/crates/webidl/src/lib.rs index 2e11b128..186f6fa7 100644 --- a/crates/webidl/src/lib.rs +++ b/crates/webidl/src/lib.rs @@ -21,6 +21,8 @@ extern crate quote; extern crate syn; extern crate wasm_bindgen_backend as backend; extern crate weedle; +#[macro_use] +extern crate lazy_static; mod error; mod first_pass; diff --git a/crates/webidl/src/util.rs b/crates/webidl/src/util.rs index 2b3b86df..5856b1bb 100644 --- a/crates/webidl/src/util.rs +++ b/crates/webidl/src/util.rs @@ -713,6 +713,7 @@ pub fn public() -> syn::Visibility { }) } + /// 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. /// @@ -721,40 +722,63 @@ pub fn public() -> syn::Visibility { /// /// 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>(mut idl_type: IdlType<'a>, id: &'a OperationId) -> IdlType<'a> { - let immutable_f32_fns: Vec<&'static str> = 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 - ]; + let op = match id { + OperationId::Operation(Some(op)) => op, + _ => return idl_type + }; - let mut immutable_f32_slice_whitelist: HashSet<&'static str> = HashSet::new(); - for function_name in immutable_f32_fns.into_iter() { - immutable_f32_slice_whitelist.insert(function_name); + if IMMUTABLE_F32_WHITELIST.contains(op) { + flag_slices_immutable(&mut idl_type) } - // example `op`... -> "vertexAttrib1fv" - if let OperationId::Operation(Some(op)) = id { - // Look up this funtion in our whitelist and see if we should make its - // slice argument immutable. - if immutable_f32_slice_whitelist.get(op).is_some() { - if let IdlType::Union(ref mut union) = idl_type { - if let IdlType::Float32Array { ref mut immutable } = union[0] { - *immutable = true; - } - } - } - } + // TODO: Add other whitelisted slices here, such as F64 or u8.. idl_type + +} + +fn flag_slices_immutable(ty: &mut IdlType) { + match ty { + IdlType::Float32Array { immutable } => *immutable = true, + IdlType::Union(list) => { + for item in list { flag_slices_immutable(item); } + } + + // TODO: ... other recursive cases like Nullable handled here + + // catch-all for everything else like Object + _ => {} + } +} + +lazy_static! { + /// These functions will have their f32 slice arguments be immutable. + static ref IMMUTABLE_F32_WHITELIST: HashSet<&'static str> = { + let mut set = HashSet::new(); + + let fn_names = 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 + ]; + + for fn_name in fn_names { + set.insert(fn_name); + } + + set + }; }