From fa653a59843b88319a2ba24adec9d6f41ea6ec56 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Thu, 17 Apr 2014 23:34:34 +0200 Subject: [PATCH 1/4] Introduce some (commented-out) tests for enumeration codegen. --- src/components/script/dom/testbinding.rs | 6 ++++++ src/components/script/dom/webidls/TestBinding.webidl | 7 ++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/components/script/dom/testbinding.rs b/src/components/script/dom/testbinding.rs index c391c44b181..53dbced8c36 100644 --- a/src/components/script/dom/testbinding.rs +++ b/src/components/script/dom/testbinding.rs @@ -45,6 +45,7 @@ impl TestBinding { pub fn StringAttribute(&self) -> DOMString { ~"" } pub fn SetStringAttribute(&self, _: DOMString) {} pub fn EnumAttribute(&self) -> TestEnum { _empty } + pub fn SetEnumAttribute(&self, _: TestEnum) {} pub fn InterfaceAttribute(&self) -> JS { Blob::new(&self.window) } pub fn SetInterfaceAttribute(&self, _: &JS) {} pub fn AnyAttribute(&self, _: *JSContext) -> JSVal { NullValue() } @@ -90,6 +91,7 @@ impl TestBinding { pub fn PassOptionalFloat(&self, _: Option) {} pub fn PassOptionalDouble(&self, _: Option) {} pub fn PassOptionalString(&self, _: Option) {} + // pub fn PassOptionalEnum(&self, _: Option) {} pub fn PassOptionalInterface(&self, _: Option>) {} pub fn PassOptionalAny(&self, _: *JSContext, _: Option) {} @@ -105,6 +107,7 @@ impl TestBinding { pub fn PassOptionalNullableFloat(&self, _: Option>) {} pub fn PassOptionalNullableDouble(&self, _: Option>) {} pub fn PassOptionalNullableString(&self, _: Option>) {} + // pub fn PassOptionalNullableEnum(&self, _: Option>) {} // pub fn PassOptionalNullableInterface(&self, _: Option>>) {} pub fn PassOptionalBooleanWithDefault(&self, _: bool) {} @@ -117,6 +120,7 @@ impl TestBinding { pub fn PassOptionalLongLongWithDefault(&self, _: i64) {} pub fn PassOptionalUnsignedLongLongWithDefault(&self, _: u64) {} pub fn PassOptionalStringWithDefault(&self, _: DOMString) {} + // pub fn PassOptionalEnumWithDefault(&self, _: TestEnum) {} pub fn PassOptionalNullableBooleanWithDefault(&self, _: Option) {} pub fn PassOptionalNullableByteWithDefault(&self, _: Option) {} @@ -130,6 +134,7 @@ impl TestBinding { pub fn PassOptionalNullableFloatWithDefault(&self, _: Option) {} pub fn PassOptionalNullableDoubleWithDefault(&self, _: Option) {} pub fn PassOptionalNullableStringWithDefault(&self, _: Option) {} + // pub fn PassOptionalNullableEnumWithDefault(&self, _: Option) {} pub fn PassOptionalNullableInterfaceWithDefault(&self, _: Option>) {} pub fn PassOptionalAnyWithDefault(&self, _: *JSContext, _: JSVal) {} @@ -145,6 +150,7 @@ impl TestBinding { // pub fn PassOptionalNullableFloatWithNonNullDefault(&self, _: Option) {} // pub fn PassOptionalNullableDoubleWithNonNullDefault(&self, _: Option) {} pub fn PassOptionalNullableStringWithNonNullDefault(&self, _: Option) {} + // pub fn PassOptionalNullableEnumWithNonNullDefault(&self, _: Option) {} } impl Reflectable for TestBinding { diff --git a/src/components/script/dom/webidls/TestBinding.webidl b/src/components/script/dom/webidls/TestBinding.webidl index 4cc2fac87f9..93196cf8e3c 100644 --- a/src/components/script/dom/webidls/TestBinding.webidl +++ b/src/components/script/dom/webidls/TestBinding.webidl @@ -17,7 +17,7 @@ interface TestBinding { attribute float floatAttribute; attribute double doubleAttribute; attribute DOMString stringAttribute; - readonly attribute TestEnum enumAttribute; + attribute TestEnum enumAttribute; attribute Blob interfaceAttribute; attribute any anyAttribute; @@ -48,6 +48,7 @@ interface TestBinding { void passOptionalFloat(optional float arg); void passOptionalDouble(optional double arg); void passOptionalString(optional DOMString arg); + // void passOptionalEnum(optional TestEnum arg); void passOptionalInterface(optional Blob arg); void passOptionalAny(optional any arg); @@ -63,6 +64,7 @@ interface TestBinding { void passOptionalNullableFloat(optional float? arg); void passOptionalNullableDouble(optional double? arg); void passOptionalNullableString(optional DOMString? arg); + // void passOptionalNullableEnum(optional TestEnum? arg); // void passOptionalNullableInterface(optional Blob? arg); void passOptionalBooleanWithDefault(optional boolean arg = false); @@ -75,6 +77,7 @@ interface TestBinding { void passOptionalLongLongWithDefault(optional long long arg = -12); void passOptionalUnsignedLongLongWithDefault(optional unsigned long long arg = 17); void passOptionalStringWithDefault(optional DOMString arg = ""); + // void passOptionalEnumWithDefault(optional TestEnum arg = "foo"); void passOptionalNullableBooleanWithDefault(optional boolean? arg = null); void passOptionalNullableByteWithDefault(optional byte? arg = null); @@ -86,6 +89,7 @@ interface TestBinding { void passOptionalNullableLongLongWithDefault(optional long long? arg = null); void passOptionalNullableUnsignedLongLongWithDefault(optional unsigned long long? arg = null); void passOptionalNullableStringWithDefault(optional DOMString? arg = null); + // void passOptionalNullableEnumWithDefault(optional TestEnum? arg = null); void passOptionalNullableInterfaceWithDefault(optional Blob? arg = null); void passOptionalAnyWithDefault(optional any arg = null); @@ -101,4 +105,5 @@ interface TestBinding { // void passOptionalNullableFloatWithNonNullDefault(optional float? arg = 0.0); // void passOptionalNullableDoubleWithNonNullDefault(optional double? arg = 0.0); void passOptionalNullableStringWithNonNullDefault(optional DOMString? arg = ""); + // void passOptionalNullableEnumWithNonNullDefault(optional TestEnum? arg = "foo"); }; From baa384536282ba042fe40e1e9e862e9cdcf01060 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Fri, 18 Apr 2014 10:09:43 +0200 Subject: [PATCH 2/4] Rewrite FindEnumStringIndex to distinguish 'value not found' and 'exception raised'. This is in preparation for handling those cases differently. --- .../dom/bindings/codegen/CodegenRust.py | 25 ++++++++----------- src/components/script/dom/bindings/utils.rs | 20 ++++++--------- 2 files changed, 19 insertions(+), 26 deletions(-) diff --git a/src/components/script/dom/bindings/codegen/CodegenRust.py b/src/components/script/dom/bindings/codegen/CodegenRust.py index 8d89fe1b879..23ad1ecd9af 100644 --- a/src/components/script/dom/bindings/codegen/CodegenRust.py +++ b/src/components/script/dom/bindings/codegen/CodegenRust.py @@ -733,23 +733,20 @@ def getJSToNativeConversionTemplate(type, descriptorProvider, failureCode=None, "yet") enum = type.inner.identifier.name if invalidEnumValueFatal: - handleInvalidEnumValueCode = " return 0;\n" + handleInvalidEnumValueCode = "return 0;" else: - handleInvalidEnumValueCode = " return 1;\n" + handleInvalidEnumValueCode = "return 1;" template = ( - "{\n" - #" int index = FindEnumStringIndex<%(invalidEnumValueFatal)s>(cx, ${val}, %(values)s, \"%(enumtype)s\", &ok);\n" - " let result = FindEnumStringIndex(cx, ${val}, %(values)s);\n" - " if result.is_err() {\n" - "%(handleInvalidEnumValueCode)s" - " }\n" - " let index = result.unwrap();\n" - " ${declName} = cast::transmute(index); //XXXjdm need some range checks up in here\n" - "}" % { "enumtype" : enum, - "values" : enum + "Values::strings", - "invalidEnumValueFatal" : toStringBool(invalidEnumValueFatal), - "handleInvalidEnumValueCode" : handleInvalidEnumValueCode }) + "match FindEnumStringIndex(cx, ${val}, %(values)s) {\n" + " Err(_) => { %(handleInvalidEnumValueCode)s },\n" + " Ok(None) => { %(handleInvalidEnumValueCode)s },\n" + " Ok(Some(index)) => {\n" + " //XXXjdm need some range checks up in here.\n" + " ${declName} = cast::transmute(index);\n" + " },\n" + "}" % { "values" : enum + "Values::strings", +"handleInvalidEnumValueCode" : handleInvalidEnumValueCode }) if defaultValue is not None: assert(defaultValue.type.tag() == IDLType.Tags.domstring) diff --git a/src/components/script/dom/bindings/utils.rs b/src/components/script/dom/bindings/utils.rs index 71c82ae86dc..05d84c2f451 100644 --- a/src/components/script/dom/bindings/utils.rs +++ b/src/components/script/dom/bindings/utils.rs @@ -470,29 +470,25 @@ pub fn InitIds(cx: *JSContext, specs: &[JSPropertySpec], ids: &mut [jsid]) -> bo pub fn FindEnumStringIndex(cx: *JSContext, v: JSVal, - values: &[&'static str]) -> Result { + values: &[&'static str]) -> Result, ()> { unsafe { let jsstr = JS_ValueToString(cx, v); if jsstr.is_null() { return Err(()); } + let length = 0; let chars = JS_GetStringCharsAndLength(cx, jsstr, &length); if chars.is_null() { return Err(()); } - for (i, value) in values.iter().enumerate() { - let equal = value.len() == length as uint && - range(0, length as int).all(|j| { - value[j] as u16 == *chars.offset(j) - }); - if equal { - return Ok(i); - } - } - - return Err(()); //XXX pass in behaviour for value not found + Ok(values.iter().enumerate().find(|&(_, value)| { + value.len() == length as uint && + range(0, length as int).all(|j| { + value[j] as u16 == *chars.offset(j) + }) + }).map(|(i, _)| i)) } } From d53841b016d21ce08c80b1147456e85719637a12 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Fri, 18 Apr 2014 10:16:21 +0200 Subject: [PATCH 3/4] Handle exceptions from FindEnumStringIndex correctly. The previous code would return success from the JSNative with a pending exception, potentially leading to assertion failures inside the JS engine later. --- src/components/script/dom/bindings/codegen/CodegenRust.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/script/dom/bindings/codegen/CodegenRust.py b/src/components/script/dom/bindings/codegen/CodegenRust.py index 23ad1ecd9af..2110ab7ebd9 100644 --- a/src/components/script/dom/bindings/codegen/CodegenRust.py +++ b/src/components/script/dom/bindings/codegen/CodegenRust.py @@ -739,13 +739,14 @@ def getJSToNativeConversionTemplate(type, descriptorProvider, failureCode=None, template = ( "match FindEnumStringIndex(cx, ${val}, %(values)s) {\n" - " Err(_) => { %(handleInvalidEnumValueCode)s },\n" + " Err(_) => { %(exceptionCode)s },\n" " Ok(None) => { %(handleInvalidEnumValueCode)s },\n" " Ok(Some(index)) => {\n" " //XXXjdm need some range checks up in here.\n" " ${declName} = cast::transmute(index);\n" " },\n" "}" % { "values" : enum + "Values::strings", + "exceptionCode" : exceptionCode, "handleInvalidEnumValueCode" : handleInvalidEnumValueCode }) if defaultValue is not None: From 4d20d1716d2068c5594b8184e2839238958a66e4 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Fri, 18 Apr 2014 10:21:50 +0200 Subject: [PATCH 4/4] Implement support for default values for enumeration arguments. --- .../script/dom/bindings/codegen/CodegenRust.py | 10 +++++----- src/components/script/dom/testbinding.rs | 2 +- src/components/script/dom/webidls/TestBinding.webidl | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/components/script/dom/bindings/codegen/CodegenRust.py b/src/components/script/dom/bindings/codegen/CodegenRust.py index 2110ab7ebd9..9df2e31649a 100644 --- a/src/components/script/dom/bindings/codegen/CodegenRust.py +++ b/src/components/script/dom/bindings/codegen/CodegenRust.py @@ -751,11 +751,11 @@ def getJSToNativeConversionTemplate(type, descriptorProvider, failureCode=None, if defaultValue is not None: assert(defaultValue.type.tag() == IDLType.Tags.domstring) - template = "" #XXXjdm unfinished - #template = handleDefault(template, - # ("${declName} = %sValues::%s;" % - # (enum, - # getEnumValueName(defaultValue.value)))) + template = handleDefault(template, + ("${declName} = %sValues::%s;" % + (enum, + getEnumValueName(defaultValue.value)))) + return (template, CGGeneric(enum), None, isOptional, None) if type.isCallback(): diff --git a/src/components/script/dom/testbinding.rs b/src/components/script/dom/testbinding.rs index 53dbced8c36..363db6e0ee0 100644 --- a/src/components/script/dom/testbinding.rs +++ b/src/components/script/dom/testbinding.rs @@ -120,7 +120,7 @@ impl TestBinding { pub fn PassOptionalLongLongWithDefault(&self, _: i64) {} pub fn PassOptionalUnsignedLongLongWithDefault(&self, _: u64) {} pub fn PassOptionalStringWithDefault(&self, _: DOMString) {} - // pub fn PassOptionalEnumWithDefault(&self, _: TestEnum) {} + pub fn PassOptionalEnumWithDefault(&self, _: TestEnum) {} pub fn PassOptionalNullableBooleanWithDefault(&self, _: Option) {} pub fn PassOptionalNullableByteWithDefault(&self, _: Option) {} diff --git a/src/components/script/dom/webidls/TestBinding.webidl b/src/components/script/dom/webidls/TestBinding.webidl index 93196cf8e3c..56f54bb461b 100644 --- a/src/components/script/dom/webidls/TestBinding.webidl +++ b/src/components/script/dom/webidls/TestBinding.webidl @@ -77,7 +77,7 @@ interface TestBinding { void passOptionalLongLongWithDefault(optional long long arg = -12); void passOptionalUnsignedLongLongWithDefault(optional unsigned long long arg = 17); void passOptionalStringWithDefault(optional DOMString arg = ""); - // void passOptionalEnumWithDefault(optional TestEnum arg = "foo"); + void passOptionalEnumWithDefault(optional TestEnum arg = "foo"); void passOptionalNullableBooleanWithDefault(optional boolean? arg = null); void passOptionalNullableByteWithDefault(optional byte? arg = null);