Skip to content

Commit 03fa00d

Browse files
committed
Make the slice argument of texImage2D and related functions immutable
This also adds immutable slice whitelisting for Uint8Array, ArrayBufferView, and BufferSource, and removes Uint8ArrayMut.
1 parent 8db85dd commit 03fa00d

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)