Skip to content

Commit 90c3196

Browse files
authored
Merge pull request #1333 from nstoddard/master
Make the slice argument of texImage2D and related functions immutable
2 parents c857a93 + 03fa00d commit 90c3196

File tree

6 files changed

+109
-33
lines changed

6 files changed

+109
-33
lines changed

crates/web-sys/tests/wasm/element.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,11 @@ export function new_webgl_rendering_context() {
156156
return canvas.getContext('webgl');
157157
}
158158

159+
export function new_webgl2_rendering_context() {
160+
const canvas = document.createElement('canvas');
161+
return canvas.getContext('webgl2');
162+
}
163+
159164
export function new_xpath_result() {
160165
let xmlDoc = new DOMParser().parseFromString("<root><value>tomato</value></root>", "application/xml");
161166
let xpathResult = xmlDoc.evaluate("/root//value", xmlDoc, null, XPathResult.ANY_TYPE, null);

crates/web-sys/tests/wasm/whitelisted_immutable_slices.rs

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,12 @@
1212
1313
use wasm_bindgen::prelude::*;
1414
use wasm_bindgen_test::*;
15-
use web_sys::WebGlRenderingContext;
15+
use web_sys::{WebGlRenderingContext, WebGl2RenderingContext};
1616

1717
#[wasm_bindgen(module = "/tests/wasm/element.js")]
1818
extern "C" {
1919
fn new_webgl_rendering_context() -> WebGlRenderingContext;
20+
fn new_webgl2_rendering_context() -> WebGl2RenderingContext;
2021
// TODO: Add a function to create another type to test here.
2122
// These functions come from element.js
2223
}
@@ -49,8 +50,41 @@ extern "C" {
4950
// gl.uniform_matrix2fv_with_f32_array(None, false, &[1.]);
5051
// gl.uniform_matrix3fv_with_f32_array(None, false, &[1.]);
5152
// gl.uniform_matrix4fv_with_f32_array(None, false, &[1.]);
52-
//}
53+
//
54+
// gl.tex_image_2d_with_i32_and_i32_and_i32_and_format_and_type_and_opt_u8_array(
55+
// 0,
56+
// 0,
57+
// 0,
58+
// 0,
59+
// 0,
60+
// 0,
61+
// 0,
62+
// 0,
63+
// Some(&[1]),
64+
// );
65+
// gl.tex_sub_image_2d_with_i32_and_i32_and_u32_and_type_and_opt_u8_array(
66+
// 0,
67+
// 0,
68+
// 0,
69+
// 0,
70+
// 0,
71+
// 0,
72+
// 0,
73+
// 0,
74+
// Some(&[1]),
75+
// );
76+
// gl.compressed_tex_image_2d_with_u8_array(0, 0, 0, 0, 0, 0, &[1]);
77+
// }
78+
//
79+
//#[wasm_bindgen_test]
80+
//fn test_webgl2_rendering_context_immutable_slices() {
81+
// let gl = new_webgl2_rendering_context();
5382

83+
// gl.tex_image_3d_with_opt_u8_array(0, 0, 0, 0, 0, 0, 0, 0, 0, Some(&[1]));
84+
// gl.tex_sub_image_3d_with_opt_u8_array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Some(&[1]));
85+
// gl.compressed_tex_image_3d_with_u8_array(0, 0, 0, 0, 0, 0, 0, &[1]);
86+
//}
87+
//
5488
// TODO:
5589
//#[wasm_bindgen_test]
5690
//fn test_another_types_immutable_slices_here() {

crates/webidl/src/first_pass.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ pub(crate) struct FirstPassRecord<'src> {
3737
pub(crate) dictionaries: BTreeMap<&'src str, DictionaryData<'src>>,
3838
pub(crate) callbacks: BTreeSet<&'src str>,
3939
pub(crate) callback_interfaces: BTreeMap<&'src str, CallbackInterfaceData<'src>>,
40-
pub(crate) immutable_f32_whitelist: BTreeSet<&'static str>,
40+
pub(crate) immutable_slice_whitelist: BTreeSet<&'static str>,
4141
}
4242

4343
/// We need to collect interface data during the first pass, to be used later.

crates/webidl/src/idl_type.rs

Lines changed: 52 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,10 @@ pub(crate) enum IdlType<'a> {
3434
ArrayBuffer,
3535
DataView,
3636
Int8Array,
37-
Uint8Array,
38-
Uint8ArrayMut,
37+
Uint8Array {
38+
/// Whether or not the generated web-sys function should use an immutable slice
39+
immutable: bool,
40+
},
3941
Uint8ClampedArray,
4042
Int16Array,
4143
Uint16Array,
@@ -46,8 +48,14 @@ pub(crate) enum IdlType<'a> {
4648
immutable: bool,
4749
},
4850
Float64Array,
49-
ArrayBufferView,
50-
BufferSource,
51+
ArrayBufferView {
52+
/// Whether or not the generated web-sys function should use an immutable slice
53+
immutable: bool,
54+
},
55+
BufferSource {
56+
/// Whether or not the generated web-sys function should use an immutable slice
57+
immutable: bool,
58+
},
5159

5260
Interface(&'a str),
5361
Dictionary(&'a str),
@@ -327,15 +335,6 @@ impl<'a> ToIdlType<'a> for Identifier<'a> {
327335
}
328336
}
329337

330-
// We default to Float32Array's being mutable, but in certain cases where we're certain that
331-
// slices won't get mutated on the JS side (such as the WebGL APIs) we might, later in the flow,
332-
// instead use the immutable version.
333-
impl<'a> ToIdlType<'a> for term::Float32Array {
334-
fn to_idl_type(&self, _record: &FirstPassRecord<'a>) -> IdlType<'a> {
335-
IdlType::Float32Array { immutable: false }
336-
}
337-
}
338-
339338
macro_rules! terms_to_idl_type {
340339
($($t:tt => $r:tt)*) => ($(
341340
impl<'a> ToIdlType<'a> for term::$t {
@@ -346,6 +345,19 @@ macro_rules! terms_to_idl_type {
346345
)*);
347346
}
348347

348+
// We default to arrays being mutable, but in certain cases where we're certain that
349+
// slices won't get mutated on the JS side (such as the WebGL APIs) we might, later in the flow,
350+
// instead use the immutable version.
351+
macro_rules! terms_to_idl_type_maybe_immutable {
352+
($($t:tt => $r:tt)*) => ($(
353+
impl<'a> ToIdlType<'a> for term::$t {
354+
fn to_idl_type(&self, _record: &FirstPassRecord<'a>) -> IdlType<'a> {
355+
IdlType::$r { immutable: false }
356+
}
357+
}
358+
)*);
359+
}
360+
349361
terms_to_idl_type! {
350362
Symbol => Symbol
351363
ByteString => ByteString
@@ -366,14 +378,18 @@ terms_to_idl_type! {
366378
Int8Array => Int8Array
367379
Int16Array => Int16Array
368380
Int32Array => Int32Array
369-
Uint8Array => Uint8Array
370381
Uint16Array => Uint16Array
371382
Uint32Array => Uint32Array
372383
Uint8ClampedArray => Uint8ClampedArray
373384
Float64Array => Float64Array
385+
Error => Error
386+
}
387+
388+
terms_to_idl_type_maybe_immutable! {
389+
Uint8Array => Uint8Array
390+
Float32Array => Float32Array
374391
ArrayBufferView => ArrayBufferView
375392
BufferSource => BufferSource
376-
Error => Error
377393
}
378394

379395
impl<'a> IdlType<'a> {
@@ -400,17 +416,16 @@ impl<'a> IdlType<'a> {
400416
IdlType::ArrayBuffer => dst.push_str("array_buffer"),
401417
IdlType::DataView => dst.push_str("data_view"),
402418
IdlType::Int8Array => dst.push_str("i8_array"),
403-
IdlType::Uint8Array => dst.push_str("u8_array"),
404-
IdlType::Uint8ArrayMut => dst.push_str("u8_array"),
419+
IdlType::Uint8Array { .. } => dst.push_str("u8_array"),
405420
IdlType::Uint8ClampedArray => dst.push_str("u8_clamped_array"),
406421
IdlType::Int16Array => dst.push_str("i16_array"),
407422
IdlType::Uint16Array => dst.push_str("u16_array"),
408423
IdlType::Int32Array => dst.push_str("i32_array"),
409424
IdlType::Uint32Array => dst.push_str("u32_array"),
410425
IdlType::Float32Array { .. } => dst.push_str("f32_array"),
411426
IdlType::Float64Array => dst.push_str("f64_array"),
412-
IdlType::ArrayBufferView => dst.push_str("array_buffer_view"),
413-
IdlType::BufferSource => dst.push_str("buffer_source"),
427+
IdlType::ArrayBufferView { .. } => dst.push_str("array_buffer_view"),
428+
IdlType::BufferSource { .. } => dst.push_str("buffer_source"),
414429

415430
IdlType::Interface(name) => dst.push_str(&snake_case_ident(name)),
416431
IdlType::UnknownInterface(name) => dst.push_str(&snake_case_ident(name)),
@@ -513,8 +528,7 @@ impl<'a> IdlType<'a> {
513528
IdlType::ArrayBuffer => js_sys("ArrayBuffer"),
514529
IdlType::DataView => None,
515530
IdlType::Int8Array => Some(array("i8", pos, false)),
516-
IdlType::Uint8Array => Some(array("u8", pos, false)),
517-
IdlType::Uint8ArrayMut => Some(array("u8", pos, false)),
531+
IdlType::Uint8Array { immutable } => Some(array("u8", pos, *immutable)),
518532
IdlType::Uint8ClampedArray => Some(clamped(array("u8", pos, false))),
519533
IdlType::Int16Array => Some(array("i16", pos, false)),
520534
IdlType::Uint16Array => Some(array("u16", pos, false)),
@@ -523,7 +537,7 @@ impl<'a> IdlType<'a> {
523537
IdlType::Float32Array { immutable } => Some(array("f32", pos, *immutable)),
524538
IdlType::Float64Array => Some(array("f64", pos, false)),
525539

526-
IdlType::ArrayBufferView | IdlType::BufferSource => js_sys("Object"),
540+
IdlType::ArrayBufferView { .. } | IdlType::BufferSource { .. } => js_sys("Object"),
527541
IdlType::Interface(name)
528542
| IdlType::Dictionary(name)
529543
| IdlType::CallbackInterface { name, .. } => {
@@ -654,8 +668,22 @@ impl<'a> IdlType<'a> {
654668
.iter()
655669
.flat_map(|idl_type| idl_type.flatten())
656670
.collect(),
657-
IdlType::ArrayBufferView => vec![IdlType::ArrayBufferView, IdlType::Uint8ArrayMut],
658-
IdlType::BufferSource => vec![IdlType::BufferSource, IdlType::Uint8ArrayMut],
671+
IdlType::ArrayBufferView { immutable } => vec![
672+
IdlType::ArrayBufferView {
673+
immutable: *immutable,
674+
},
675+
IdlType::Uint8Array {
676+
immutable: *immutable,
677+
},
678+
],
679+
IdlType::BufferSource { immutable } => vec![
680+
IdlType::BufferSource {
681+
immutable: *immutable,
682+
},
683+
IdlType::Uint8Array {
684+
immutable: *immutable,
685+
},
686+
],
659687
IdlType::LongLong => vec![IdlType::Long, IdlType::Double],
660688
IdlType::UnsignedLongLong => vec![IdlType::UnsignedLong, IdlType::Double],
661689
IdlType::CallbackInterface {

crates/webidl/src/lib.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ fn parse(webidl_source: &str, allowed_types: Option<&[&str]>) -> Result<Program>
8282

8383
let mut first_pass_record: FirstPassRecord = Default::default();
8484
first_pass_record.builtin_idents = builtin_idents();
85-
first_pass_record.immutable_f32_whitelist = immutable_f32_whitelist();
85+
first_pass_record.immutable_slice_whitelist = immutable_slice_whitelist();
8686

8787
definitions.first_pass(&mut first_pass_record, ())?;
8888
let mut program = Default::default();
@@ -181,9 +181,9 @@ fn builtin_idents() -> BTreeSet<Ident> {
181181
)
182182
}
183183

184-
fn immutable_f32_whitelist() -> BTreeSet<&'static str> {
184+
fn immutable_slice_whitelist() -> BTreeSet<&'static str> {
185185
BTreeSet::from_iter(vec![
186-
// WebGlRenderingContext
186+
// WebGlRenderingContext, WebGl2RenderingContext
187187
"uniform1fv",
188188
"uniform2fv",
189189
"uniform3fv",
@@ -195,6 +195,14 @@ fn immutable_f32_whitelist() -> BTreeSet<&'static str> {
195195
"vertexAttrib2fv",
196196
"vertexAttrib3fv",
197197
"vertexAttrib4fv",
198+
"bufferData",
199+
"texImage2D",
200+
"texSubImage2D",
201+
"compressedTexImage2D",
202+
// WebGl2RenderingContext
203+
"texImage3D",
204+
"texSubImage3D",
205+
"compressedTexImage3D",
198206
// TODO: Add another type's functions here. Leave a comment header with the type name
199207
])
200208
}

crates/webidl/src/util.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -647,12 +647,10 @@ impl<'src> FirstPassRecord<'src> {
647647
_ => return idl_type,
648648
};
649649

650-
if self.immutable_f32_whitelist.contains(op) {
650+
if self.immutable_slice_whitelist.contains(op) {
651651
flag_slices_immutable(&mut idl_type)
652652
}
653653

654-
// TODO: Add other whitelisted slices here, such as F64 or u8..
655-
656654
idl_type
657655
}
658656
}
@@ -737,7 +735,10 @@ pub fn public() -> syn::Visibility {
737735

738736
fn flag_slices_immutable(ty: &mut IdlType) {
739737
match ty {
738+
IdlType::Uint8Array { immutable } => *immutable = true,
740739
IdlType::Float32Array { immutable } => *immutable = true,
740+
IdlType::ArrayBufferView { immutable } => *immutable = true,
741+
IdlType::BufferSource { immutable } => *immutable = true,
741742
IdlType::Nullable(item) => flag_slices_immutable(item),
742743
IdlType::FrozenArray(item) => flag_slices_immutable(item),
743744
IdlType::Sequence(item) => flag_slices_immutable(item),

0 commit comments

Comments
 (0)