diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2016-05-13 02:47:08 -0700 |
---|---|---|
committer | bors-servo <lbergstrom+bors@mozilla.com> | 2016-05-13 02:47:08 -0700 |
commit | 221db56b08e01157c97f5adba43799eeaee32f64 (patch) | |
tree | e7eb8f7149367de5b818c8981321b8600ff8a0d1 /components/script/dom | |
parent | 03465ad8c77f03ae2f538d046ae1e1dc86f04723 (diff) | |
parent | 91101f6226033a663ea8e4bb215f72ab8d206da7 (diff) | |
download | servo-221db56b08e01157c97f5adba43799eeaee32f64.tar.gz servo-221db56b08e01157c97f5adba43799eeaee32f64.zip |
Auto merge of #11155 - emilio:codegen-dict-keyword, r=Ms2ger
codegen: Fix dictionary handling and semantics
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
- [x] These changes fix #11152 (github issue number if applicable).
Either:
- [x] There are tests for these changes OR
- [ ] These changes do not require tests because _____
Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process.
Fixes #11152
<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="35" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/11155)
<!-- Reviewable:end -->
Diffstat (limited to 'components/script/dom')
-rw-r--r-- | components/script/dom/bindings/codegen/CodegenRust.py | 40 | ||||
-rw-r--r-- | components/script/dom/bindings/utils.rs | 7 | ||||
-rw-r--r-- | components/script/dom/testbinding.rs | 73 | ||||
-rw-r--r-- | components/script/dom/webidls/TestBinding.webidl | 9 |
4 files changed, 112 insertions, 17 deletions
diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py index 3c0593d6e58..076b7bd642f 100644 --- a/components/script/dom/bindings/codegen/CodegenRust.py +++ b/components/script/dom/bindings/codegen/CodegenRust.py @@ -662,12 +662,17 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None, '%s' % (firstCap(sourceDescription), exceptionCode))), post="\n") + def onFailureInvalidEnumValue(failureCode, passedVarName): + return CGGeneric( + failureCode or + ('throw_type_error(cx, &format!("\'{}\' is not a valid enum value for enumeration \'%s\'.", %s)); %s' + % (type.name, passedVarName, exceptionCode))) + def onFailureNotCallable(failureCode): - return CGWrapper( - CGGeneric( - failureCode or - ('throw_type_error(cx, \"%s is not callable.\");\n' - '%s' % (firstCap(sourceDescription), exceptionCode)))) + return CGGeneric( + failureCode or + ('throw_type_error(cx, \"%s is not callable.\");\n' + '%s' % (firstCap(sourceDescription), exceptionCode))) # A helper function for handling null default values. Checks that the # default value, if it exists, is null. @@ -868,15 +873,15 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None, "yet") enum = type.inner.identifier.name if invalidEnumValueFatal: - handleInvalidEnumValueCode = exceptionCode + handleInvalidEnumValueCode = onFailureInvalidEnumValue(failureCode, 'search').define() else: handleInvalidEnumValueCode = "return true;" template = ( "match find_enum_string_index(cx, ${val}, %(values)s) {\n" " Err(_) => { %(exceptionCode)s },\n" - " Ok(None) => { %(handleInvalidEnumValueCode)s },\n" - " Ok(Some(index)) => {\n" + " Ok((None, search)) => { %(handleInvalidEnumValueCode)s },\n" + " Ok((Some(index), _)) => {\n" " //XXXjdm need some range checks up in here.\n" " mem::transmute(index)\n" " },\n" @@ -5295,14 +5300,23 @@ class CGDictionary(CGThing): conversion = self.getMemberConversion(memberInfo, member.type) return CGGeneric("%s: %s,\n" % (name, conversion.define())) + def varInsert(varName, dictionaryName): + insertion = ("let mut %s_js = RootedValue::new(cx, UndefinedValue());\n" + "%s.to_jsval(cx, %s_js.handle_mut());\n" + "set_dictionary_property(cx, obj.handle(), \"%s\", %s_js.handle()).unwrap();" + % (varName, varName, varName, dictionaryName, varName)) + return CGGeneric(insertion) + def memberInsert(memberInfo): member, _ = memberInfo name = self.makeMemberName(member.identifier.name) - insertion = ("let mut %s = RootedValue::new(cx, UndefinedValue());\n" - "self.%s.to_jsval(cx, %s.handle_mut());\n" - "set_dictionary_property(cx, obj.handle(), \"%s\", %s.handle()).unwrap();" - % (name, name, name, name, name)) - return CGGeneric("%s\n" % insertion) + if member.optional and not member.defaultValue: + insertion = CGIfWrapper("let Some(ref %s) = self.%s" % (name, name), + varInsert(name, member.identifier.name)) + else: + insertion = CGGeneric("let %s = &self.%s;\n%s" % + (name, name, varInsert(name, member.identifier.name).define())) + return CGGeneric("%s\n" % insertion.define()) memberInits = CGList([memberInit(m) for m in self.memberInfo]) memberInserts = CGList([memberInsert(m) for m in self.memberInfo]) diff --git a/components/script/dom/bindings/utils.rs b/components/script/dom/bindings/utils.rs index 9b9a729fe0a..cf1cf37a8b9 100644 --- a/components/script/dom/bindings/utils.rs +++ b/components/script/dom/bindings/utils.rs @@ -39,6 +39,7 @@ use std::ptr; use std::slice; use util::non_geckolib::jsstring_to_str; use util::prefs; +use util::str::DOMString; /// Proxy handler for a WindowProxy. pub struct WindowProxyHandler(pub *const libc::c_void); @@ -182,18 +183,18 @@ pub fn get_array_index_from_id(_cx: *mut JSContext, id: HandleId) -> Option<u32> /// Find the index of a string given by `v` in `values`. /// Returns `Err(())` on JSAPI failure (there is a pending exception), and -/// `Ok(None)` if there was no matching string. +/// `Ok((None, value))` if there was no matching string. pub unsafe fn find_enum_string_index(cx: *mut JSContext, v: HandleValue, values: &[&'static str]) - -> Result<Option<usize>, ()> { + -> Result<(Option<usize>, DOMString), ()> { let jsstr = ToString(cx, v); if jsstr.is_null() { return Err(()); } let search = jsstring_to_str(cx, jsstr); - Ok(values.iter().position(|value| search == *value)) + Ok((values.iter().position(|value| search == *value), search)) } /// Returns wether `obj` is a platform object diff --git a/components/script/dom/testbinding.rs b/components/script/dom/testbinding.rs index f8b45599b18..6dfe66a9d75 100644 --- a/components/script/dom/testbinding.rs +++ b/components/script/dom/testbinding.rs @@ -6,7 +6,9 @@ use dom::bindings::codegen::Bindings::EventListenerBinding::EventListener; use dom::bindings::codegen::Bindings::FunctionBinding::Function; -use dom::bindings::codegen::Bindings::TestBindingBinding::{self, TestBindingMethods, TestEnum}; +use dom::bindings::codegen::Bindings::TestBindingBinding; +use dom::bindings::codegen::Bindings::TestBindingBinding::{TestBindingMethods, TestDictionary}; +use dom::bindings::codegen::Bindings::TestBindingBinding::{TestDictionaryDefaults, TestEnum}; use dom::bindings::codegen::UnionTypes::{BlobOrBoolean, BlobOrBlobSequence}; use dom::bindings::codegen::UnionTypes::{BlobOrString, BlobOrUnsignedLong, EventOrString}; use dom::bindings::codegen::UnionTypes::{EventOrUSVString, HTMLElementOrLong}; @@ -286,6 +288,75 @@ impl TestBindingMethods for TestBinding { Some(UnsignedLongOrBoolean::UnsignedLong(0u32)) } fn ReceiveNullableSequence(&self) -> Option<Vec<i32>> { Some(vec![1]) } + fn ReceiveTestDictionaryWithSuccessOnKeyword(&self) -> TestDictionary { + TestDictionary { + anyValue: NullValue(), + booleanValue: None, + byteValue: None, + dict: TestDictionaryDefaults { + UnrestrictedDoubleValue: 0.0, + anyValue: NullValue(), + booleanValue: false, + byteValue: 0, + doubleValue: Finite::new(1.0).unwrap(), + enumValue: TestEnum::Foo, + floatValue: Finite::new(1.0).unwrap(), + longLongValue: 54, + longValue: 12, + nullableBooleanValue: None, + nullableByteValue: None, + nullableDoubleValue: None, + nullableFloatValue: None, + nullableLongLongValue: None, + nullableLongValue: None, + nullableObjectValue: ptr::null_mut(), + nullableOctetValue: None, + nullableShortValue: None, + nullableStringValue: None, + nullableUnrestrictedDoubleValue: None, + nullableUnrestrictedFloatValue: None, + nullableUnsignedLongLongValue: None, + nullableUnsignedLongValue: None, + nullableUnsignedShortValue: None, + nullableUsvstringValue: None, + octetValue: 0, + shortValue: 0, + stringValue: DOMString::new(), + unrestrictedFloatValue: 0.0, + unsignedLongLongValue: 0, + unsignedLongValue: 0, + unsignedShortValue: 0, + usvstringValue: USVString("".to_owned()), + }, + doubleValue: None, + enumValue: None, + floatValue: None, + interfaceValue: None, + longLongValue: None, + longValue: None, + objectValue: None, + octetValue: None, + requiredValue: true, + seqDict: None, + shortValue: None, + stringValue: None, + type_: Some(DOMString::from("success")), + unrestrictedDoubleValue: None, + unrestrictedFloatValue: None, + unsignedLongLongValue: None, + unsignedLongValue: None, + unsignedShortValue: None, + usvstringValue: None, + nonRequiredNullable: None, + nonRequiredNullable2: Some(None), // null + } + } + + fn DictMatchesPassedValues(&self, arg: &TestDictionary) -> bool { + arg.type_.as_ref().map(|s| s == "success").unwrap_or(false) && + arg.nonRequiredNullable.is_none() && + arg.nonRequiredNullable2 == Some(None) + } fn PassBoolean(&self, _: bool) {} fn PassByte(&self, _: i8) {} diff --git a/components/script/dom/webidls/TestBinding.webidl b/components/script/dom/webidls/TestBinding.webidl index d0bfbbfef2a..6706ccfdaa9 100644 --- a/components/script/dom/webidls/TestBinding.webidl +++ b/components/script/dom/webidls/TestBinding.webidl @@ -30,6 +30,13 @@ dictionary TestDictionary { object objectValue; TestDictionaryDefaults dict; sequence<TestDictionaryDefaults> seqDict; + // Reserved rust keyword + DOMString type; + // These are used to test bidirectional conversion + // and differentiation of non-required and nullable types + // in dictionaries. + DOMString? nonRequiredNullable; + DOMString? nonRequiredNullable2; }; dictionary TestDictionaryDefaults { @@ -196,6 +203,8 @@ interface TestBinding { (sequence<long> or boolean)? receiveNullableUnion4(); (unsigned long or boolean)? receiveNullableUnion5(); sequence<long>? receiveNullableSequence(); + TestDictionary receiveTestDictionaryWithSuccessOnKeyword(); + boolean dictMatchesPassedValues(TestDictionary arg); void passBoolean(boolean arg); void passByte(byte arg); |