mirror of
https://github.com/servo/servo.git
synced 2025-08-05 21:50:18 +01:00
Auto merge of #20267 - Xanewok:typed-arrays-stack-heap-variants, r=Xanewok
Support JS typed arrays as arguments and in WebIDL unions <!-- Please describe your changes on the following line: --> Supersedes #20205. This brings support to receiving typed arrays as function arguments (those are stack-rooted with CustomAutoRooter) and also being a member of a union (which is basically heap-rooted? similarly to other webidl unions). This is based on my other PR #20265 (which means it has to pull an external rust-mozjs branch and contains some also slightly unrelated changes here) since it shares `RootedTraceableBox::from_box` here and some other additional changes at rust-mozjs, but it can be easily separated if needed. I tried adding support to nullable typed arrays but couldn't work around an issue of codegen always sticking a "OrNull" at the end of my type (presumably because of [this](https://github.com/servo/servo/blob/master/components/script/dom/bindings/codegen/parser/WebIDL.py#L2241)?). How would I go about avoiding the suffix with nullable arguments? If we were to add also support for nullable typed arrays then I think we wouldn't be blocked anymore on this in WebGL 1.0. r? @jdm --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [ ] These changes fix #__ (github issue number if applicable). <!-- Either: --> - [ ] There are tests for these changes OR - [ ] These changes do not require tests because _____ <!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.--> <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/20267) <!-- Reviewable:end -->
This commit is contained in:
commit
f7ee1befc5
8 changed files with 91 additions and 12 deletions
8
Cargo.lock
generated
8
Cargo.lock
generated
|
@ -1620,7 +1620,7 @@ dependencies = [
|
|||
"cssparser 0.23.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hashglobe 0.1.0",
|
||||
"mozjs 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mozjs 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"selectors 0.19.0",
|
||||
"servo_arc 0.1.1",
|
||||
"smallbitvec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1795,7 +1795,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "mozjs"
|
||||
version = "0.1.14"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -2462,7 +2462,7 @@ dependencies = [
|
|||
"mime_guess 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mitochondria 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mozangle 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mozjs 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mozjs 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"msg 0.0.1",
|
||||
"net_traits 0.0.1",
|
||||
"num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -3844,7 +3844,7 @@ dependencies = [
|
|||
"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
|
||||
"checksum mitochondria 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9de3eca27871df31c33b807f834b94ef7d000956f57aa25c5aed9c5f0aae8f6f"
|
||||
"checksum mozangle 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4d916e4f2d39a00eeeb082ceb7c63c741e7c9d4f7915945f9225ae5e3b284092"
|
||||
"checksum mozjs 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "23e86a4da33f9325da4ccc652506284e00ff20f06d63f721eaebeb804eaca62d"
|
||||
"checksum mozjs 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "79645a302ffcef7ca2673ff4db4d4273b87671dd0de4d53da889b664dd555e74"
|
||||
"checksum mozjs_sys 0.50.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e61a792a125b1364c5ec50255ed8343ce02dc56098f8868dd209d472c8de006a"
|
||||
"checksum mp3-metadata 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ab5f1d2693586420208d1200ce5a51cd44726f055b635176188137aff42c7de"
|
||||
"checksum mp4parse 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f821e3799bc0fd16d9b861fb02fa7ee1b5fba29f45ad591dade105c48ca9a1a0"
|
||||
|
|
|
@ -16,7 +16,7 @@ app_units = "0.6"
|
|||
cssparser = "0.23.0"
|
||||
euclid = "0.17"
|
||||
hashglobe = { path = "../hashglobe" }
|
||||
mozjs = { version = "0.1.8", features = ["promises"], optional = true }
|
||||
mozjs = { version = "0.2", features = ["promises"], optional = true }
|
||||
selectors = { path = "../selectors" }
|
||||
servo_arc = { path = "../servo_arc" }
|
||||
smallbitvec = "1.0.3"
|
||||
|
|
|
@ -62,7 +62,7 @@ metrics = {path = "../metrics"}
|
|||
mitochondria = "1.1.2"
|
||||
mime = "0.2.1"
|
||||
mime_guess = "1.8.0"
|
||||
mozjs = { version = "0.1.10", features = ["promises"]}
|
||||
mozjs = { version = "0.2", features = ["promises"]}
|
||||
msg = {path = "../msg"}
|
||||
net_traits = {path = "../net_traits"}
|
||||
num-traits = "0.1.32"
|
||||
|
|
|
@ -870,8 +870,51 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
|||
|
||||
return handleOptional(templateBody, declType, handleDefaultNull("None"))
|
||||
|
||||
if type.isSpiderMonkeyInterface():
|
||||
raise TypeError("Can't handle SpiderMonkey interface arguments yet")
|
||||
if is_typed_array(type):
|
||||
if failureCode is None:
|
||||
substitutions = {
|
||||
"sourceDescription": sourceDescription,
|
||||
"exceptionCode": exceptionCode,
|
||||
}
|
||||
unwrapFailureCode = string.Template(
|
||||
'throw_type_error(cx, "${sourceDescription} is not a typed array.");\n'
|
||||
'${exceptionCode}').substitute(substitutions)
|
||||
else:
|
||||
unwrapFailureCode = failureCode
|
||||
|
||||
typeName = type.unroll().name # unroll because it may be nullable
|
||||
|
||||
if isMember == "Union":
|
||||
typeName = "Heap" + typeName
|
||||
|
||||
templateBody = fill(
|
||||
"""
|
||||
match typedarray::${ty}::from($${val}.get().to_object()) {
|
||||
Ok(val) => val,
|
||||
Err(()) => {
|
||||
$*{failureCode}
|
||||
}
|
||||
}
|
||||
""",
|
||||
ty=typeName,
|
||||
failureCode=unwrapFailureCode + "\n",
|
||||
)
|
||||
|
||||
if isMember == "Union":
|
||||
templateBody = "RootedTraceableBox::new(%s)" % templateBody
|
||||
|
||||
declType = CGGeneric("typedarray::%s" % typeName)
|
||||
if type.nullable():
|
||||
templateBody = "Some(%s)" % templateBody
|
||||
declType = CGWrapper(declType, pre="Option<", post=">")
|
||||
|
||||
templateBody = wrapObjectTemplate(templateBody, "None",
|
||||
isDefinitelyObject, type, failureCode)
|
||||
|
||||
return handleOptional(templateBody, declType, handleDefaultNull("None"))
|
||||
|
||||
elif type.isSpiderMonkeyInterface():
|
||||
raise TypeError("Can't handle SpiderMonkey interface arguments other than typed arrays yet")
|
||||
|
||||
if type.isDOMString():
|
||||
nullBehavior = getConversionConfigForType(type, isEnforceRange, isClamp, treatNullAs)
|
||||
|
@ -2287,6 +2330,7 @@ def UnionTypes(descriptors, dictionaries, callbacks, typedefs, config):
|
|||
'js::jsapi::JSObject',
|
||||
'js::jsapi::MutableHandleValue',
|
||||
'js::jsval::JSVal',
|
||||
'js::typedarray'
|
||||
]
|
||||
|
||||
# Now find all the things we'll need as arguments and return values because
|
||||
|
@ -4138,6 +4182,9 @@ def getUnionTypeTemplateVars(type, descriptorProvider):
|
|||
elif type.isObject():
|
||||
name = type.name
|
||||
typeName = "Heap<*mut JSObject>"
|
||||
elif is_typed_array(type):
|
||||
name = type.name
|
||||
typeName = "typedarray::Heap" + name
|
||||
else:
|
||||
raise TypeError("Can't handle %s in unions yet" % type)
|
||||
|
||||
|
@ -5688,6 +5735,7 @@ def generate_imports(config, cgthings, descriptors, callbacks=None, dictionaries
|
|||
'js::jsapi::MutableHandleValue',
|
||||
'js::jsapi::ObjectOpResult',
|
||||
'js::jsapi::PropertyDescriptor',
|
||||
'js::jsapi::Rooted',
|
||||
'js::jsapi::RootedId',
|
||||
'js::jsapi::RootedObject',
|
||||
'js::jsapi::RootedString',
|
||||
|
@ -5719,6 +5767,7 @@ def generate_imports(config, cgthings, descriptors, callbacks=None, dictionaries
|
|||
'js::rust::define_methods',
|
||||
'js::rust::define_properties',
|
||||
'js::rust::get_object_class',
|
||||
'js::typedarray',
|
||||
'dom',
|
||||
'dom::bindings',
|
||||
'dom::bindings::codegen::InterfaceObjectMap',
|
||||
|
@ -6419,6 +6468,9 @@ def type_needs_tracing(t):
|
|||
if t.isUnion():
|
||||
return any(type_needs_tracing(member) for member in t.flatMemberTypes)
|
||||
|
||||
if is_typed_array(t):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
if t.isDictionary():
|
||||
|
@ -6439,6 +6491,12 @@ def type_needs_tracing(t):
|
|||
assert False, (t, type(t))
|
||||
|
||||
|
||||
def is_typed_array(t):
|
||||
assert isinstance(t, IDLObject), (t, type(t))
|
||||
|
||||
return t.isTypedArray() or t.isArrayBuffer() or t.isArrayBufferView() or t.isSharedArrayBuffer()
|
||||
|
||||
|
||||
def type_needs_auto_root(t):
|
||||
"""
|
||||
Certain IDL types, such as `sequence<any>` or `sequence<object>` need to be
|
||||
|
@ -6449,6 +6507,9 @@ def type_needs_auto_root(t):
|
|||
if t.isType():
|
||||
if t.isSequence() and (t.inner.isAny() or t.inner.isObject()):
|
||||
return True
|
||||
# SpiderMonkey interfaces, we currently don't support any other except typed arrays
|
||||
if is_typed_array(t):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
|
|
@ -62,6 +62,8 @@ use js::glue::{CallObjectTracer, CallValueTracer};
|
|||
use js::jsapi::{GCTraceKindToAscii, Heap, JSObject, JSTracer, TraceKind};
|
||||
use js::jsval::JSVal;
|
||||
use js::rust::Runtime;
|
||||
use js::typedarray::TypedArray;
|
||||
use js::typedarray::TypedArrayElement;
|
||||
use metrics::{InteractiveMetrics, InteractiveWindow};
|
||||
use msg::constellation_msg::{BrowsingContextId, PipelineId, TopLevelBrowsingContextId};
|
||||
use net_traits::{Metadata, NetworkError, ReferrerPolicy, ResourceThreads};
|
||||
|
@ -658,6 +660,12 @@ unsafe impl JSTraceable for StyleLocked<MediaList> {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe impl<T> JSTraceable for TypedArray<T, Box<Heap<*mut JSObject>>> where T: TypedArrayElement {
|
||||
unsafe fn trace(&self, trc: *mut JSTracer) {
|
||||
self.underlying_object().trace(trc);
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<S> JSTraceable for DocumentStylesheetSet<S>
|
||||
where
|
||||
S: JSTraceable + ::style::stylesheets::StylesheetInDocument + PartialEq + 'static,
|
||||
|
|
|
@ -38,6 +38,7 @@ use js::jsapi::{HandleObject, HandleValue, Heap, JSContext, JSObject};
|
|||
use js::jsapi::{JS_NewPlainObject, JS_NewUint8ClampedArray};
|
||||
use js::jsval::{JSVal, NullValue};
|
||||
use js::rust::CustomAutoRooterGuard;
|
||||
use js::typedarray;
|
||||
use script_traits::MsDuration;
|
||||
use servo_config::prefs::PREFS;
|
||||
use std::borrow::ToOwned;
|
||||
|
@ -436,6 +437,9 @@ impl TestBindingMethods for TestBinding {
|
|||
fn PassByteString(&self, _: ByteString) {}
|
||||
fn PassEnum(&self, _: TestEnum) {}
|
||||
fn PassInterface(&self, _: &Blob) {}
|
||||
fn PassTypedArray(&self, _: CustomAutoRooterGuard<typedarray::Int8Array>) {}
|
||||
fn PassTypedArray2(&self, _: CustomAutoRooterGuard<typedarray::ArrayBuffer>) {}
|
||||
fn PassTypedArray3(&self, _: CustomAutoRooterGuard<typedarray::ArrayBufferView>) {}
|
||||
fn PassUnion(&self, _: HTMLElementOrLong) {}
|
||||
fn PassUnion2(&self, _: EventOrString) {}
|
||||
fn PassUnion3(&self, _: BlobOrString) {}
|
||||
|
@ -447,6 +451,7 @@ impl TestBindingMethods for TestBinding {
|
|||
fn PassUnion9(&self, _: UnionTypes::TestDictionaryOrLong) {}
|
||||
#[allow(unsafe_code)]
|
||||
unsafe fn PassUnion10(&self, _: *mut JSContext, _: UnionTypes::StringOrObject) {}
|
||||
fn PassUnion11(&self, _: UnionTypes::ArrayBufferOrArrayBufferView) {}
|
||||
fn PassUnionWithTypedef(&self, _: DocumentOrTestTypedef) {}
|
||||
fn PassUnionWithTypedef2(&self, _: LongSequenceOrTestTypedef) {}
|
||||
#[allow(unsafe_code)]
|
||||
|
@ -487,6 +492,7 @@ impl TestBindingMethods for TestBinding {
|
|||
fn PassNullableInterface(&self, _: Option<&Blob>) {}
|
||||
#[allow(unsafe_code)]
|
||||
unsafe fn PassNullableObject(&self, _: *mut JSContext, _: *mut JSObject) {}
|
||||
fn PassNullableTypedArray(&self, _: CustomAutoRooterGuard<Option<typedarray::Int8Array>>) { }
|
||||
fn PassNullableUnion(&self, _: Option<HTMLElementOrLong>) {}
|
||||
fn PassNullableUnion2(&self, _: Option<EventOrString>) {}
|
||||
fn PassNullableUnion3(&self, _: Option<StringOrLongSequence>) {}
|
||||
|
|
|
@ -46,7 +46,7 @@ use euclid::Size2D;
|
|||
use fnv::FnvHashMap;
|
||||
use half::f16;
|
||||
use js::conversions::ConversionBehavior;
|
||||
use js::jsapi::{JSContext, JSObject, Type, Rooted};
|
||||
use js::jsapi::{JSContext, JSObject, Type};
|
||||
use js::jsval::{BooleanValue, DoubleValue, Int32Value, JSVal, NullValue, UndefinedValue};
|
||||
use js::typedarray::{TypedArray, TypedArrayElement, Float32, Int32};
|
||||
use net_traits::image::base::PixelFormat;
|
||||
|
@ -1182,9 +1182,8 @@ unsafe fn typed_array_or_sequence_to_vec<T>(cx: *mut JSContext,
|
|||
<T::Element as FromJSValConvertible>::Config: Clone,
|
||||
{
|
||||
// TODO(servo/rust-mozjs#330): replace this with a macro that supports generic types.
|
||||
let mut typed_array_root = Rooted::new_unrooted();
|
||||
let typed_array: Option<TypedArray<T>> =
|
||||
TypedArray::from(cx, &mut typed_array_root, sequence_or_abv).ok();
|
||||
let typed_array: Option<TypedArray<T, *mut JSObject>> =
|
||||
TypedArray::from(sequence_or_abv).ok();
|
||||
if let Some(mut typed_array) = typed_array {
|
||||
return Ok(typed_array.as_slice().to_vec());
|
||||
}
|
||||
|
|
|
@ -248,6 +248,9 @@ interface TestBinding {
|
|||
void passByteString(ByteString arg);
|
||||
void passEnum(TestEnum arg);
|
||||
void passInterface(Blob arg);
|
||||
void passTypedArray(Int8Array arg);
|
||||
void passTypedArray2(ArrayBuffer arg);
|
||||
void passTypedArray3(ArrayBufferView arg);
|
||||
void passUnion((HTMLElement or long) arg);
|
||||
void passUnion2((Event or DOMString) data);
|
||||
void passUnion3((Blob or DOMString) data);
|
||||
|
@ -258,6 +261,7 @@ interface TestBinding {
|
|||
void passUnion8((sequence<ByteString> or long) arg);
|
||||
void passUnion9((TestDictionary or long) arg);
|
||||
void passUnion10((DOMString or object) arg);
|
||||
void passUnion11((ArrayBuffer or ArrayBufferView) arg);
|
||||
void passUnionWithTypedef((Document or TestTypedef) arg);
|
||||
void passUnionWithTypedef2((sequence<long> or TestTypedef) arg);
|
||||
void passAny(any arg);
|
||||
|
@ -290,6 +294,7 @@ interface TestBinding {
|
|||
// void passNullableEnum(TestEnum? arg);
|
||||
void passNullableInterface(Blob? arg);
|
||||
void passNullableObject(object? arg);
|
||||
void passNullableTypedArray(Int8Array? arg);
|
||||
void passNullableUnion((HTMLElement or long)? arg);
|
||||
void passNullableUnion2((Event or DOMString)? data);
|
||||
void passNullableUnion3((DOMString or sequence<long>)? data);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue