From 423774779f0a47f2b5e5b5226cca9b2d56ebf368 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Tue, 31 Jul 2012 00:22:23 -0400 Subject: [PATCH] Bug 771636 part 3. Implement default values for WebIDL strings. r=peterv --- dom/bindings/BindingUtils.h | 8 ++--- dom/bindings/Codegen.py | 46 ++++++++++++++------------- dom/bindings/test/TestBindingHeader.h | 2 ++ dom/bindings/test/TestCodeGen.webidl | 3 ++ 4 files changed, 31 insertions(+), 28 deletions(-) diff --git a/dom/bindings/BindingUtils.h b/dom/bindings/BindingUtils.h index 61ed5de6afcb..13f292bac9b6 100644 --- a/dom/bindings/BindingUtils.h +++ b/dom/bindings/BindingUtils.h @@ -857,6 +857,7 @@ enum StringificationBehavior { eNull }; +// pval must not be null and must point to a rooted JS::Value static inline bool ConvertJSValueToString(JSContext* cx, const JS::Value& v, JS::Value* pval, StringificationBehavior nullBehavior, @@ -876,12 +877,7 @@ ConvertJSValueToString(JSContext* cx, const JS::Value& v, JS::Value* pval, behavior = eStringify; } - // If pval is null, that means the argument was optional and - // not passed; turn those into void strings if they're - // supposed to be stringified. - if (behavior != eStringify || !pval) { - // Here behavior == eStringify implies !pval, so both eNull and - // eStringify should end up with void strings. + if (behavior != eStringify) { if (behavior == eEmpty) { result.Truncate(); } else { diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py index 45c518e33a61..cc78cbcc4e48 100644 --- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -2040,17 +2040,24 @@ for (uint32_t i = 0; i < length; ++i) { nullBehavior = "eStringify" undefinedBehavior = "eStringify" - if defaultValue is not None: - if not isinstance(defaultValue, IDLNullValue): - raise TypeError("Can't handle non-null default values for " - "strings yet") - if not type.nullable(): - raise TypeError("Null default value for non-nullable string") - val = "(${haveValue}) ? ${val} : JSVAL_NULL" - valPtr = "(${haveValue}) ? ${valPtr} : NULL" - else: - val = "${val}" - valPtr = "${valPtr}" + def getConversionCode(varName): + conversionCode = ( + "if (!ConvertJSValueToString(cx, ${val}, ${valPtr}, %s, %s, %s)) {\n" + " return false;\n" + "}" % (nullBehavior, undefinedBehavior, varName)) + if defaultValue is None: + return conversionCode + + if isinstance(defaultValue, IDLNullValue): + assert(type.nullable()) + return handleDefault(conversionCode, + "%s.SetNull()" % varName) + return handleDefault( + conversionCode, + ("static const PRUnichar data[] = { %s, 0 };\n" + "%s.SetData(data, ArrayLength(data) - 1)" % + (", ".join("'" + char + "'" for char in defaultValue.value), + varName))) if isMember: # We have to make a copy, because our jsval may well not @@ -2059,25 +2066,20 @@ for (uint32_t i = 0; i < length; ++i) { return ( "{\n" " FakeDependentString str;\n" - " if (!ConvertJSValueToString(cx, %s, %s, %s, %s, str)) {\n" - " return false;\n" - " }\n" + "%s\n" " ${declName} = str;\n" - "}\n" % - (val, valPtr, nullBehavior, undefinedBehavior), - declType, None, - isOptional) + "}\n" % CGIndenter(CGGeneric(getConversionCode("str"))).define(), + declType, None, isOptional) if isOptional: declType = "Optional" else: declType = "NonNull" + return ( - "if (!ConvertJSValueToString(cx, %s, %s, %s, %s, ${holderName})) {\n" - " return false;\n" - "}\n" + "%s\n" "const_cast<%s&>(${declName}) = &${holderName};" % - (val, valPtr, nullBehavior, undefinedBehavior, declType), + (getConversionCode("${holderName}"), declType), CGGeneric("const " + declType), CGGeneric("FakeDependentString"), # No need to deal with Optional here; we have handled it already False) diff --git a/dom/bindings/test/TestBindingHeader.h b/dom/bindings/test/TestBindingHeader.h index 7c19b5098263..129641291375 100644 --- a/dom/bindings/test/TestBindingHeader.h +++ b/dom/bindings/test/TestBindingHeader.h @@ -335,6 +335,7 @@ public: void PassString(const nsAString&, ErrorResult&); void PassNullableString(const nsAString&, ErrorResult&); void PassOptionalString(const Optional&, ErrorResult&); + void PassOptionalStringWithDefaultValue(const nsAString&, ErrorResult&); void PassOptionalNullableString(const Optional&, ErrorResult&); void PassOptionalNullableStringWithDefaultValue(const nsAString&, ErrorResult&); @@ -551,6 +552,7 @@ private: void PassString(nsAString&, ErrorResult&) MOZ_DELETE; void PassNullableString(nsAString&, ErrorResult&) MOZ_DELETE; void PassOptionalString(Optional&, ErrorResult&) MOZ_DELETE; + void PassOptionalStringWithDefaultValue(nsAString&, ErrorResult&) MOZ_DELETE; void PassOptionalNullableString(Optional&, ErrorResult&) MOZ_DELETE; void PassOptionalNullableStringWithDefaultValue(nsAString&, ErrorResult&) MOZ_DELETE; diff --git a/dom/bindings/test/TestCodeGen.webidl b/dom/bindings/test/TestCodeGen.webidl index a7e2f3dcc938..6f37ef67d5f7 100644 --- a/dom/bindings/test/TestCodeGen.webidl +++ b/dom/bindings/test/TestCodeGen.webidl @@ -233,6 +233,7 @@ interface TestInterface { void passString(DOMString arg); void passNullableString(DOMString? arg); void passOptionalString(optional DOMString arg); + void passOptionalStringWithDefaultValue(optional DOMString arg = "abc"); void passOptionalNullableString(optional DOMString? arg); void passOptionalNullableStringWithDefaultValue(optional DOMString? arg = null); @@ -357,6 +358,8 @@ dictionary Dict : ParentDict { long z = 9; DOMString str; TestEnum otherEnum = "b"; + DOMString otherStr = "def"; + DOMString? yetAnotherStr = null; }; dictionary ParentDict : GrandparentDict {