Title: [204978] trunk/Source/WebCore
Revision
204978
Author
wei...@apple.com
Date
2016-08-25 11:36:05 -0700 (Thu, 25 Aug 2016)

Log Message

Add the ability to override the implementation name of IDL enums and dictionaries
https://bugs.webkit.org/show_bug.cgi?id=161185

Reviewed by Anders Carlsson.

* bindings/scripts/CodeGenerator.pm:
(ProcessDocument):
Build a dictionary of IDL name -> implementation name overrides
for enums and dictionaries up front based on ImplementedAs extended
attribute.

(HasEnumImplementationNameOverride):
(GetEnumImplementationNameOverride):
(HasDictionaryImplementationNameOverride):
(GetDictionaryImplementationNameOverride):
Expose predicate and getter for name overrides.

* bindings/scripts/CodeGeneratorJS.pm:
(GetEnumerationClassName):
(GetDictionaryClassName):
Use the override names as necessary.

* bindings/scripts/test/TestObj.idl:
Add tests for enums and dictionaries with ImplementedAs extended
attributes.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (204977 => 204978)


--- trunk/Source/WebCore/ChangeLog	2016-08-25 18:23:54 UTC (rev 204977)
+++ trunk/Source/WebCore/ChangeLog	2016-08-25 18:36:05 UTC (rev 204978)
@@ -1,3 +1,31 @@
+2016-08-24  Sam Weinig  <s...@webkit.org>
+
+        Add the ability to override the implementation name of IDL enums and dictionaries
+        https://bugs.webkit.org/show_bug.cgi?id=161185
+
+        Reviewed by Anders Carlsson.
+
+        * bindings/scripts/CodeGenerator.pm:
+        (ProcessDocument):
+        Build a dictionary of IDL name -> implementation name overrides
+        for enums and dictionaries up front based on ImplementedAs extended
+        attribute.
+
+        (HasEnumImplementationNameOverride):
+        (GetEnumImplementationNameOverride):
+        (HasDictionaryImplementationNameOverride):
+        (GetDictionaryImplementationNameOverride):
+        Expose predicate and getter for name overrides.
+
+        * bindings/scripts/CodeGeneratorJS.pm:
+        (GetEnumerationClassName):
+        (GetDictionaryClassName):
+        Use the override names as necessary.
+
+        * bindings/scripts/test/TestObj.idl:
+        Add tests for enums and dictionaries with ImplementedAs extended
+        attributes.
+
 2016-08-25  Johan K. Jensen  <johan_jen...@apple.com>
 
         Don't store networkLoadTiming in the disk cache

Modified: trunk/Source/WebCore/bindings/scripts/CodeGenerator.pm (204977 => 204978)


--- trunk/Source/WebCore/bindings/scripts/CodeGenerator.pm	2016-08-25 18:23:54 UTC (rev 204977)
+++ trunk/Source/WebCore/bindings/scripts/CodeGenerator.pm	2016-08-25 18:36:05 UTC (rev 204978)
@@ -70,9 +70,13 @@
     "SerializedScriptValue" => 1,
 );
 
-my %enumTypeHash = ();
 my %dictionaryTypes = ();
+my %dictionaryTypeImplementationNameOverrides = ();
 
+my %enumTypeHash = ();
+my %enumTypeImplementationNameOverrides = ();
+
+
 my %typedArrayTypes = (
     "ArrayBuffer" => 1,
     "ArrayBufferView" => 1,
@@ -163,9 +167,20 @@
     my $ifaceName = "CodeGenerator" . $useGenerator;
     require $ifaceName . ".pm";
 
-    %enumTypeHash = map { $_->name => $_->values } @{$useDocument->enumerations};
-    %dictionaryTypes = map { $_->name => 1 } @{$useDocument->dictionaries};
+    foreach my $dictionary (@{$useDocument->dictionaries}) {
+        $dictionaryTypes{$dictionary->name} = 1;
+        if ($dictionary->extendedAttributes->{"ImplementedAs"}) {
+            $dictionaryTypeImplementationNameOverrides{$dictionary->name} = $dictionary->extendedAttributes->{"ImplementedAs"};
+        }
+    }
 
+    foreach my $enumeration (@{$useDocument->enumerations}) {
+        $enumTypeHash{$enumeration->name} = $enumeration->values;
+        if ($enumeration->extendedAttributes->{"ImplementedAs"}) {
+            $enumTypeImplementationNameOverrides{$enumeration->name} = $enumeration->extendedAttributes->{"ImplementedAs"};
+        }
+    }
+
     # Dynamically load external code generation perl module
     $codeGenerator = $ifaceName->new($object, $writeDependencies, $verbose, $targetIdlFilePath);
     unless (defined($codeGenerator)) {
@@ -395,8 +410,7 @@
 # Currently used outside WebKit in an internal Apple project; can be removed soon.
 sub IsStringType
 {
-    my $object = shift;
-    my $type = shift;
+    my ($object, $type) = @_;
 
     return 1 if $type eq "DOMString";
     return 1 if $type eq "USVString";
@@ -405,8 +419,7 @@
 
 sub IsEnumType
 {
-    my $object = shift;
-    my $type = shift;
+    my ($object, $type) = @_;
 
     return 1 if exists $enumTypeHash{$type};
     return 0;
@@ -414,19 +427,49 @@
 
 sub ValidEnumValues
 {
-    my $object = shift;
-    my $type = shift;
+    my ($object, $type) = @_;
 
     return @{$enumTypeHash{$type}};
 }
 
+sub HasEnumImplementationNameOverride
+{
+    my ($object, $type) = @_;
+
+    return 1 if exists $enumTypeImplementationNameOverrides{$type};
+    return 0;
+}
+
+sub GetEnumImplementationNameOverride
+{
+    my ($object, $type) = @_;
+
+    return $enumTypeImplementationNameOverrides{$type};
+}
+
 sub IsDictionaryType
 {
     my ($object, $type) = @_;
 
-    return $dictionaryTypes{$type} || 0;
+    return 1 if exists $dictionaryTypes{$type};
+    return 0;
 }
 
+sub HasDictionaryImplementationNameOverride
+{
+    my ($object, $type) = @_;
+
+    return 1 if exists $dictionaryTypeImplementationNameOverrides{$type};
+    return 0;
+}
+
+sub GetDictionaryImplementationNameOverride
+{
+    my ($object, $type) = @_;
+
+    return $dictionaryTypeImplementationNameOverrides{$type};
+}
+
 sub IsNonPointerType
 {
     my ($object, $type) = @_;

Modified: trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm (204977 => 204978)


--- trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm	2016-08-25 18:23:54 UTC (rev 204977)
+++ trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm	2016-08-25 18:36:05 UTC (rev 204978)
@@ -807,6 +807,10 @@
 {
     my ($interface, $name) = @_;
 
+    if ($codeGenerator->HasEnumImplementationNameOverride($name)) {
+        return $codeGenerator->GetEnumImplementationNameOverride($name);
+    }
+
     return GetNestedClassName($interface, $name);
 }
 
@@ -922,6 +926,10 @@
 {
     my ($interface, $name) = @_;
 
+    if ($codeGenerator->HasDictionaryImplementationNameOverride($name)) {
+        return $codeGenerator->GetDictionaryImplementationNameOverride($name);
+    }
+
     return GetNestedClassName($interface, $name);
 }
 

Modified: trunk/Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp (204977 => 204978)


--- trunk/Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp	2016-08-25 18:23:54 UTC (rev 204977)
+++ trunk/Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp	2016-08-25 18:36:05 UTC (rev 204978)
@@ -194,6 +194,49 @@
     return "\"\", \"OptionalValue1\", \"OptionalValue2\", \"OptionalValue3\"";
 }
 
+JSString* jsStringWithCache(ExecState*, AlternateEnumName);
+
+JSString* jsStringWithCache(ExecState* state, AlternateEnumName enumerationValue)
+{
+    static NeverDestroyed<const String> values[] = {
+        ASCIILiteral("enumValue1"),
+        ASCIILiteral("EnumValue2"),
+    };
+    static_assert(static_cast<size_t>(AlternateEnumName::EnumValue1) == 0, "AlternateEnumName::EnumValue1 is not 0 as expected");
+    static_assert(static_cast<size_t>(AlternateEnumName::EnumValue2) == 1, "AlternateEnumName::EnumValue2 is not 1 as expected");
+    ASSERT(static_cast<size_t>(enumerationValue) < WTF_ARRAY_LENGTH(values));
+    return jsStringWithCache(state, values[static_cast<size_t>(enumerationValue)]);
+}
+
+template<> struct JSValueTraits<AlternateEnumName> {
+    static JSString* arrayJSValue(ExecState* state, JSDOMGlobalObject*, AlternateEnumName value) { return jsStringWithCache(state, value); }
+};
+
+template<> Optional<AlternateEnumName> parse<AlternateEnumName>(ExecState& state, JSValue value)
+{
+    auto stringValue = value.toWTFString(&state);
+    if (stringValue == "enumValue1")
+        return AlternateEnumName::EnumValue1;
+    if (stringValue == "EnumValue2")
+        return AlternateEnumName::EnumValue2;
+    return Nullopt;
+}
+
+template<> AlternateEnumName convert<AlternateEnumName>(ExecState& state, JSValue value)
+{
+    auto result = parse<AlternateEnumName>(state, value);
+    if (UNLIKELY(!result)) {
+        throwTypeError(&state);
+        return { };
+    }
+    return result.value();
+}
+
+template<> inline const char* expectedEnumerationValues<AlternateEnumName>()
+{
+    return "\"enumValue1\", \"EnumValue2\"";
+}
+
 #if ENABLE(Condition1)
 
 JSString* jsStringWithCache(ExecState*, TestObj::EnumA);
@@ -594,6 +637,22 @@
     return TestObj::DictionaryThatShouldTolerateNull { WTFMove(enumerationValue), WTFMove(booleanWithoutDefault) };
 }
 
+template<> Optional<AlternateDictionaryName> convertDictionary<AlternateDictionaryName>(ExecState& state, JSValue value)
+{
+    if (value.isUndefinedOrNull())
+        return AlternateDictionaryName { { }, { } };
+    auto* object = value.getObject();
+    if (UNLIKELY(!object || object->type() == RegExpObjectType)) {
+        throwTypeError(&state);
+        return Nullopt;
+    }
+    auto enumerationValue = convertOptional<TestObj::EnumType>(state, object->get(&state, Identifier::fromString(&state, "enumerationValue")));
+    if (UNLIKELY(state.hadException()))
+        return Nullopt;
+    auto booleanWithoutDefault = convertOptional<bool>(state, object->get(&state, Identifier::fromString(&state, "booleanWithoutDefault")));
+    return AlternateDictionaryName { WTFMove(enumerationValue), WTFMove(booleanWithoutDefault) };
+}
+
 // Functions
 
 #if ENABLE(TEST_FEATURE)
@@ -774,6 +833,8 @@
 bool setJSTestObjStringAttrTreatingNullAsEmptyString(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);
 JSC::EncodedJSValue jsTestObjUsvstringAttrTreatingNullAsEmptyString(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
 bool setJSTestObjUsvstringAttrTreatingNullAsEmptyString(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);
+JSC::EncodedJSValue jsTestObjImplementationEnumAttr(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
+bool setJSTestObjImplementationEnumAttr(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);
 JSC::EncodedJSValue jsTestObjXMLObjAttr(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
 bool setJSTestObjXMLObjAttr(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);
 JSC::EncodedJSValue jsTestObjCreate(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
@@ -1096,6 +1157,7 @@
     { "lenientTestObjAttr", CustomAccessor, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjLenientTestObjAttr), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSTestObjLenientTestObjAttr) } },
     { "stringAttrTreatingNullAsEmptyString", CustomAccessor, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjStringAttrTreatingNullAsEmptyString), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSTestObjStringAttrTreatingNullAsEmptyString) } },
     { "usvstringAttrTreatingNullAsEmptyString", CustomAccessor, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjUsvstringAttrTreatingNullAsEmptyString), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSTestObjUsvstringAttrTreatingNullAsEmptyString) } },
+    { "implementationEnumAttr", CustomAccessor, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjImplementationEnumAttr), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSTestObjImplementationEnumAttr) } },
     { "XMLObjAttr", CustomAccessor, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjXMLObjAttr), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSTestObjXMLObjAttr) } },
     { "create", CustomAccessor, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjCreate), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSTestObjCreate) } },
     { "reflectedStringAttr", CustomAccessor, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjReflectedStringAttr), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSTestObjReflectedStringAttr) } },
@@ -1784,6 +1846,21 @@
 }
 
 
+EncodedJSValue jsTestObjImplementationEnumAttr(ExecState* state, EncodedJSValue thisValue, PropertyName)
+{
+    UNUSED_PARAM(state);
+    UNUSED_PARAM(thisValue);
+    JSValue decodedThisValue = JSValue::decode(thisValue);
+    auto* castedThis = jsDynamicCast<JSTestObj*>(decodedThisValue);
+    if (UNLIKELY(!castedThis)) {
+        return throwGetterTypeError(*state, "TestObject", "implementationEnumAttr");
+    }
+    auto& impl = castedThis->wrapped();
+    JSValue result = jsStringWithCache(state, impl.implementationEnumAttr());
+    return JSValue::encode(result);
+}
+
+
 EncodedJSValue jsTestObjXMLObjAttr(ExecState* state, EncodedJSValue thisValue, PropertyName)
 {
     UNUSED_PARAM(state);
@@ -3111,6 +3188,25 @@
 }
 
 
+bool setJSTestObjImplementationEnumAttr(ExecState* state, EncodedJSValue thisValue, EncodedJSValue encodedValue)
+{
+    JSValue value = JSValue::decode(encodedValue);
+    UNUSED_PARAM(thisValue);
+    JSTestObj* castedThis = jsDynamicCast<JSTestObj*>(JSValue::decode(thisValue));
+    if (UNLIKELY(!castedThis)) {
+        return throwSetterTypeError(*state, "TestObject", "implementationEnumAttr");
+    }
+    auto& impl = castedThis->wrapped();
+    auto nativeValue = parse<AlternateEnumName>(*state, value);
+    if (UNLIKELY(state->hadException()))
+        return false;
+    if (UNLIKELY(!nativeValue))
+        return false;
+    impl.setImplementationEnumAttr(nativeValue.value());
+    return true;
+}
+
+
 bool setJSTestObjXMLObjAttr(ExecState* state, EncodedJSValue thisValue, EncodedJSValue encodedValue)
 {
     JSValue value = JSValue::decode(encodedValue);

Modified: trunk/Source/WebCore/bindings/scripts/test/TestObj.idl (204977 => 204978)


--- trunk/Source/WebCore/bindings/scripts/test/TestObj.idl	2016-08-25 18:23:54 UTC (rev 204977)
+++ trunk/Source/WebCore/bindings/scripts/test/TestObj.idl	2016-08-25 18:36:05 UTC (rev 204978)
@@ -2,7 +2,7 @@
  * Copyright (C) 2009 Google Inc. All rights reserved.
  * Copyright (C) 2010 Apple Inc. All rights reserved.
  *
- * Redistribution and use in source and binary formstrArg, with or without
+ * Redistribution and use in source and binary form, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
@@ -28,7 +28,7 @@
  */
 
 // This IDL file is for testing the bindings code generator and for tracking
-// changes in its ouput.
+// changes in its output.
 
 enum TestEnumType { "", "enumValue1", "EnumValue2", "EnumValue3" };
 
@@ -35,6 +35,8 @@
 // Leading underscore on an enum should be removed.
 enum _optional { "", "OptionalValue1", "OptionalValue2", "OptionalValue3" };
 
+[ImplementedAs=AlternateEnumName] enum TestEnumTypeWithAlternateImplementationName { "enumValue1", "EnumValue2" };
+
 [Conditional=Condition1] enum TestEnumA { "A" };
 [Conditional=Condition1&Condition2] enum TestEnumB { "B" };
 [Conditional=Condition1|Condition2] enum TestEnumC { "C" };
@@ -79,6 +81,8 @@
     [TreatNullAs=EmptyString] attribute USVString usvstringAttrTreatingNullAsEmptyString;
 #endif
 
+    attribute TestEnumTypeWithAlternateImplementationName implementationEnumAttr;
+
     // WK_ucfirst, WK_lcfirst exceptional cases.
     attribute TestObj                  XMLObjAttr;
     attribute boolean                  create;
@@ -449,3 +453,10 @@
     TestEnumType enumerationValue;
     boolean booleanWithoutDefault;
 };
+
+[
+    ImplementedAs=AlternateDictionaryName
+] dictionary TestDictionaryWithAlternateImplementationName {
+    TestEnumType enumerationValue;
+    boolean booleanWithoutDefault;
+};
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to