Title: [208893] trunk
Revision
208893
Author
[email protected]
Date
2016-11-18 13:47:42 -0800 (Fri, 18 Nov 2016)

Log Message

[WebIDL] Add support for record types
https://bugs.webkit.org/show_bug.cgi?id=164935

Reviewed by Tim Horton.

Source/WebCore:

Add support for WebIDLs record types. We map them to HashMap<String, {OtherType}>.

* bindings/generic/IDLTypes.h:
- Add IDLRecord type and helper predicate.
- Remove IDLRegExp which is no longer in WebIDL and we never supported.

* bindings/js/JSDOMBinding.cpp:
(WebCore::stringToByteString):
(WebCore::identifierToByteString):
(WebCore::valueToByteString):
(WebCore::hasUnpairedSurrogate):
(WebCore::stringToUSVString):
(WebCore::identifierToUSVString):
(WebCore::valueToUSVString):
* bindings/js/JSDOMBinding.h:
Refactor ByteString and USVString conversion to support converting from
either a JSValue or Identifier.

* bindings/js/JSDOMConvert.h:
(WebCore::DetailConverter<IDLRecord<K, V>>):
(WebCore::JSConverter<IDLRecord<K, V>>):
Add conversion support for record types. Use Detail::IdentifierConverter helper
to convert identifiers to strings using the correct conversion rules.

(WebCore::Converter<IDLUnion<T...>>::convert):
Update comments in union conversion to match current spec. Remove check
for regular expressions and add support for record types.

* bindings/scripts/CodeGenerator.pm:
(IsRefPtrType):
Add record and union types to the list of things that aren't RefPtrs.

(IsRecordType):
Add predicate for testing if a type is a record.

(IsWrapperType):
Remove check for union. This is now handled in the IsRefPtrType check.

(SkipIncludeHeader): Deleted.
(GetSequenceInnerType): Deleted.
(GetFrozenArrayInnerType): Deleted.
(GetSequenceOrFrozenArrayInnerType): Deleted.
Remove no longer necessary functions.

* bindings/scripts/CodeGeneratorJS.pm:
(AddIncludesForImplementationType):
Remove check for includes to skip. This is now only called for interfaces, which should be included
unconditionally.

(AddToIncludesForIDLType):
Add includes and recursive includes for record types.

(GenerateOverloadedFunctionOrConstructor):
Update to account for records.

(GetGnuVTableRefForInterface):
(GetGnuVTableNameForInterface):
(GetGnuMangledNameForInterface):
(GetWinVTableNameForInterface):
(GetWinMangledNameForInterface):
Strength-reduce GetNativeTypeForConversions and GetNamespaceForInterface into their callers.

(GetBaseIDLType):
Add support for IDLRecord. Remove call to GetIDLInterfaceName now that is simply the type name.

(GetNativeType):
Simplify sequence/FrozenArray support and add record support.

(GetNativeInnerType):
Generalize GetNativeVectorInnerType to work for record types as well.

(ShouldPassWrapperByReference):
Moved so native type accessors can be together.

(NativeToJSValueDOMConvertNeedsState):
(NativeToJSValueDOMConvertNeedsGlobalObject):
Add record support.

(GetNativeTypeForConversions): Deleted.
(GetNamespaceForInterface): Deleted.
(GetNativeVectorType): Deleted.
(GetIDLInterfaceName): Deleted.
(GetNativeVectorInnerType): Deleted.
Remove unneeded functions.

* bindings/scripts/IDLParser.pm:
(typeDescription):
Add helper useful for debugging, that constructs the string form of a type.

(typeByApplyingTypedefs):
Add missing call to typeByApplyingTypedefs (this is noted by a fix in JSTestCallbackFunctionWithTypedefs.h)

(parseNonAnyType):
Remove unused $subtypeName variables and add support for parsing record types.

* bindings/scripts/test/JS/JSTestCallbackFunctionWithTypedefs.cpp:
* bindings/scripts/test/JS/JSTestCallbackFunctionWithTypedefs.h:
* bindings/scripts/test/JS/JSTestObj.cpp:
* bindings/scripts/test/TestObj.idl:
Add tests for records and update results.

* testing/TypeConversions.h:
(WebCore::TypeConversions::testLongRecord):
(WebCore::TypeConversions::setTestLongRecord):
(WebCore::TypeConversions::testNodeRecord):
(WebCore::TypeConversions::setTestNodeRecord):
(WebCore::TypeConversions::testSequenceRecord):
(WebCore::TypeConversions::setTestSequenceRecord):
* testing/TypeConversions.idl:
Add record types so it can be tested from layout tests.

LayoutTests:

* js/dom/webidl-type-mapping-expected.txt:
* js/dom/webidl-type-mapping.html:
Add tests for WebIDL record types.

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (208892 => 208893)


--- trunk/LayoutTests/ChangeLog	2016-11-18 21:41:40 UTC (rev 208892)
+++ trunk/LayoutTests/ChangeLog	2016-11-18 21:47:42 UTC (rev 208893)
@@ -1,3 +1,14 @@
+2016-11-18  Sam Weinig  <[email protected]>
+
+        [WebIDL] Add support for record types
+        https://bugs.webkit.org/show_bug.cgi?id=164935
+
+        Reviewed by Tim Horton.
+
+        * js/dom/webidl-type-mapping-expected.txt:
+        * js/dom/webidl-type-mapping.html:
+        Add tests for WebIDL record types.
+
 2016-11-17  Jiewen Tan  <[email protected]>
 
         Update SubtleCrypto::encrypt to match the latest spec

Modified: trunk/LayoutTests/js/dom/webidl-type-mapping-expected.txt (208892 => 208893)


--- trunk/LayoutTests/js/dom/webidl-type-mapping-expected.txt	2016-11-18 21:41:40 UTC (rev 208892)
+++ trunk/LayoutTests/js/dom/webidl-type-mapping-expected.txt	2016-11-18 21:47:42 UTC (rev 208893)
@@ -1075,6 +1075,8 @@
 PASS converter.testUSVString is "undefined"
 PASS converter.testString is "undefined"
 PASS converter.testByteString is "undefined"
+
+Testing union conversion
 converter.testUnion = 'hello'
 PASS converter.testUnion is 'hello'
 PASS typeof converter.testUnion is 'string'
@@ -1123,6 +1125,71 @@
 PASS converter.typeConversionsDictionaryUnionType is 'dictionary'
 converter.setTypeConversionsDictionary({ })
 PASS converter.typeConversionsDictionaryUnionType is 'dictionary'
+
+Testing record conversion
+converter.testLongRecord = { key: 1, key2: 2 }
+PASS converter.testLongRecord is an instance of Object
+PASS converter.testLongRecord.hasOwnProperty('key') is true
+PASS 'key' in converter.testLongRecord is true
+PASS converter.testLongRecord['key'] is 1
+PASS converter.testLongRecord.hasOwnProperty('key2') is true
+PASS 'key2' in converter.testLongRecord is true
+PASS converter.testLongRecord['key2'] is 2
+converter.testLongRecord = undefined
+PASS converter.testLongRecord is an instance of Object
+converter.testLongRecord = null
+PASS converter.testLongRecord is an instance of Object
+PASS converter.testLongRecord = 1 threw exception TypeError: Type error.
+PASS converter.testLongRecord = { key: { valueOf:function() { throw new Error(); } } } threw exception Error.
+var o = { otherKey: 2 }; Object.defineProperty(o, 'key', { enumerable: false, value: 1 }); converter.testLongRecord = o;
+PASS converter.testLongRecord.hasOwnProperty('key') is false
+PASS converter.testLongRecord.hasOwnProperty('otherKey') is true
+PASS converter.testLongRecord['otherKey'] is 2
+var o = { otherKey: 2 }; Object.defineProperty(o, 'key', { get: function() { return 1; }, enumerable: true }); converter.testLongRecord = o;
+PASS converter.testLongRecord.hasOwnProperty('key') is true
+PASS converter.testLongRecord['key'] is 1
+PASS converter.testLongRecord.hasOwnProperty('otherKey') is true
+PASS converter.testLongRecord['otherKey'] is 2
+PASS var o = { otherKey: 2 }; Object.defineProperty(o, 'key', { get: function() { throw new Error();; }, enumerable: true }); converter.testLongRecord = o; threw exception Error.
+converter.testNodeRecord = { key: document, key2: document.documentElement }
+PASS converter.testNodeRecord.hasOwnProperty('key') is true
+PASS 'key' in converter.testNodeRecord is true
+PASS converter.testNodeRecord['key'] is document
+PASS converter.testNodeRecord.hasOwnProperty('key2') is true
+PASS 'key2' in converter.testNodeRecord is true
+PASS converter.testNodeRecord['key2'] is document.documentElement
+PASS converter.testNodeRecord = { key: 'hello' } threw exception TypeError: Type error.
+converter.testLongRecord = {'í €': 1 }
+PASS converter.testLongRecord['í €'] is 1
+converter.testNodeRecord = {'í €': document }
+PASS converter.testNodeRecord['�'] is document
+converter.testLongRecord = {'í°€': 1 }
+PASS converter.testLongRecord['í°€'] is 1
+converter.testNodeRecord = {'í°€': document }
+PASS converter.testNodeRecord['�'] is document
+converter.testLongRecord = {'í €': 1 }
+PASS converter.testLongRecord['í €\0'] is 1
+converter.testNodeRecord = {'í €': document }
+PASS converter.testNodeRecord['�\0'] is document
+converter.testLongRecord = {'í°€': 1 }
+PASS converter.testLongRecord['í°€\0'] is 1
+converter.testNodeRecord = {'í°€': document }
+PASS converter.testNodeRecord['�\0'] is document
+converter.testLongRecord = {'í°€í €': 1 }
+PASS converter.testLongRecord['í°€í €'] is 1
+converter.testNodeRecord = {'í°€í €': document }
+PASS converter.testNodeRecord['��'] is document
+converter.testLongRecord = {'𝄞': 1 }
+PASS converter.testLongRecord['𝄞'] is 1
+converter.testNodeRecord = {'𝄞': document }
+PASS converter.testNodeRecord['𝄞'] is document
+converter.testSequenceRecord = { key: ['value', 'other value'] }
+PASS converter.testSequenceRecord.hasOwnProperty('key') is true
+PASS 'key' in converter.testSequenceRecord is true
+PASS converter.testSequenceRecord['key'] is ['value', 'other value']
+PASS converter.testSequenceRecord = { 'Ā': ['value'] } threw exception TypeError: Type error.
+converter.testSequenceRecord = { 'ÿ': ['value'] }
+PASS converter.testSequenceRecord['ÿ'] is ['value']
 PASS successfullyParsed is true
 
 TEST COMPLETE

Modified: trunk/LayoutTests/js/dom/webidl-type-mapping.html (208892 => 208893)


--- trunk/LayoutTests/js/dom/webidl-type-mapping.html	2016-11-18 21:41:40 UTC (rev 208892)
+++ trunk/LayoutTests/js/dom/webidl-type-mapping.html	2016-11-18 21:47:42 UTC (rev 208893)
@@ -598,7 +598,8 @@
     shouldBeEqualToString("converter.testByteString", value);
 });
 
-
+debug("");
+debug("Testing union conversion")
 evalAndLog("converter.testUnion = 'hello'");
 shouldBe("converter.testUnion", "'hello'");
 shouldBe("typeof converter.testUnion", "'string'");
@@ -650,5 +651,68 @@
 evalAndLog("converter.setTypeConversionsDictionary({ })");
 shouldBe("converter.typeConversionsDictionaryUnionType", "'dictionary'");
 
+
+debug("");
+debug("Testing record conversion")
+
+// testLongRecord is a record<DOMString, long> attribute
+// testNodeRecord is a record<USVString, Node> attribute
+// testSequenceRecord is a record<ByteString, sequence<DOMString>> attribute
+
+evalAndLog("converter.testLongRecord = { key: 1, key2: 2 }");
+shouldBeType("converter.testLongRecord", "Object");
+shouldBeTrue("converter.testLongRecord.hasOwnProperty('key')");
+shouldBeTrue("'key' in converter.testLongRecord");
+shouldBe("converter.testLongRecord['key']", "1");
+shouldBeTrue("converter.testLongRecord.hasOwnProperty('key2')");
+shouldBeTrue("'key2' in converter.testLongRecord");
+shouldBe("converter.testLongRecord['key2']", "2");
+evalAndLog("converter.testLongRecord = undefined");
+shouldBeType("converter.testLongRecord", "Object");
+evalAndLog("converter.testLongRecord = null");
+shouldBeType("converter.testLongRecord", "Object");
+shouldThrow("converter.testLongRecord = 1");
+shouldThrow("converter.testLongRecord = { key: { valueOf:function() { throw new Error(); } } }");
+evalAndLog("var o = { otherKey: 2 }; Object.defineProperty(o, 'key', { enumerable: false, value: 1 }); converter.testLongRecord = o;");
+shouldBeFalse("converter.testLongRecord.hasOwnProperty('key')");
+shouldBeTrue("converter.testLongRecord.hasOwnProperty('otherKey')");
+shouldBe("converter.testLongRecord['otherKey']", "2");
+evalAndLog("var o = { otherKey: 2 }; Object.defineProperty(o, 'key', { get: function() { return 1; }, enumerable: true }); converter.testLongRecord = o;");
+shouldBeTrue("converter.testLongRecord.hasOwnProperty('key')");
+shouldBe("converter.testLongRecord['key']", "1");
+shouldBeTrue("converter.testLongRecord.hasOwnProperty('otherKey')");
+shouldBe("converter.testLongRecord['otherKey']", "2");
+shouldThrow("var o = { otherKey: 2 }; Object.defineProperty(o, 'key', { get: function() { throw new Error();; }, enumerable: true }); converter.testLongRecord = o;");
+
+evalAndLog("converter.testNodeRecord = { key: document, key2: document.documentElement }");
+shouldBeTrue("converter.testNodeRecord.hasOwnProperty('key')");
+shouldBeTrue("'key' in converter.testNodeRecord");
+shouldBe("converter.testNodeRecord['key']", "document");
+shouldBeTrue("converter.testNodeRecord.hasOwnProperty('key2')");
+shouldBeTrue("'key2' in converter.testNodeRecord");
+shouldBe("converter.testNodeRecord['key2']", "document.documentElement");
+shouldThrow("converter.testNodeRecord = { key: 'hello' }");
+
+[{input: "\uD800", expected: "\uFFFD"},
+ {input: "\uDC00", expected: "\uFFFD"},
+ {input: "\uD800\u0000", expected: "\uFFFD\u0000"},
+ {input: "\uDC00\u0000", expected: "\uFFFD\u0000"},
+ {input: "\uDC00\uD800", expected: "\uFFFD\uFFFD"},
+ {input: "\uD834\uDD1E", expected: "\uD834\uDD1E"},
+].forEach(function(test) {
+    evalAndLog("converter.testLongRecord = {'" + test.input + "': 1 }");
+    shouldBe("converter.testLongRecord['" + test.input + "']", "1");
+    evalAndLog("converter.testNodeRecord = {'" + test.input + "': document }");
+    shouldBe("converter.testNodeRecord['" + test.expected + "']", "document");
+});
+
+evalAndLog("converter.testSequenceRecord = { key: ['value', 'other value'] }");
+shouldBeTrue("converter.testSequenceRecord.hasOwnProperty('key')");
+shouldBeTrue("'key' in converter.testSequenceRecord");
+shouldBe("converter.testSequenceRecord['key']", "['value', 'other value']");
+shouldThrow("converter.testSequenceRecord = { '\u0100': ['value'] }");
+evalAndLog("converter.testSequenceRecord = { '\u00FF': ['value'] }");
+shouldBe("converter.testSequenceRecord['\u00FF']", "['value']");
+
 </script>
 <script src=""

Modified: trunk/Source/WebCore/ChangeLog (208892 => 208893)


--- trunk/Source/WebCore/ChangeLog	2016-11-18 21:41:40 UTC (rev 208892)
+++ trunk/Source/WebCore/ChangeLog	2016-11-18 21:47:42 UTC (rev 208893)
@@ -1,3 +1,121 @@
+2016-11-18  Sam Weinig  <[email protected]>
+
+        [WebIDL] Add support for record types
+        https://bugs.webkit.org/show_bug.cgi?id=164935
+
+        Reviewed by Tim Horton.
+
+        Add support for WebIDLs record types. We map them to HashMap<String, {OtherType}>.
+
+        * bindings/generic/IDLTypes.h:
+        - Add IDLRecord type and helper predicate.
+        - Remove IDLRegExp which is no longer in WebIDL and we never supported.
+
+        * bindings/js/JSDOMBinding.cpp:
+        (WebCore::stringToByteString):
+        (WebCore::identifierToByteString):
+        (WebCore::valueToByteString):
+        (WebCore::hasUnpairedSurrogate):
+        (WebCore::stringToUSVString):
+        (WebCore::identifierToUSVString):
+        (WebCore::valueToUSVString):
+        * bindings/js/JSDOMBinding.h:
+        Refactor ByteString and USVString conversion to support converting from
+        either a JSValue or Identifier.
+
+        * bindings/js/JSDOMConvert.h:
+        (WebCore::DetailConverter<IDLRecord<K, V>>):
+        (WebCore::JSConverter<IDLRecord<K, V>>):
+        Add conversion support for record types. Use Detail::IdentifierConverter helper
+        to convert identifiers to strings using the correct conversion rules.
+
+        (WebCore::Converter<IDLUnion<T...>>::convert):
+        Update comments in union conversion to match current spec. Remove check
+        for regular expressions and add support for record types.
+
+        * bindings/scripts/CodeGenerator.pm:
+        (IsRefPtrType):
+        Add record and union types to the list of things that aren't RefPtrs.
+
+        (IsRecordType):
+        Add predicate for testing if a type is a record.
+
+        (IsWrapperType):
+        Remove check for union. This is now handled in the IsRefPtrType check.
+
+        (SkipIncludeHeader): Deleted.
+        (GetSequenceInnerType): Deleted.
+        (GetFrozenArrayInnerType): Deleted.
+        (GetSequenceOrFrozenArrayInnerType): Deleted.
+        Remove no longer necessary functions.
+
+        * bindings/scripts/CodeGeneratorJS.pm:
+        (AddIncludesForImplementationType):
+        Remove check for includes to skip. This is now only called for interfaces, which should be included
+        unconditionally.
+
+        (AddToIncludesForIDLType):
+        Add includes and recursive includes for record types.
+
+        (GenerateOverloadedFunctionOrConstructor):
+        Update to account for records.
+
+        (GetGnuVTableRefForInterface):
+        (GetGnuVTableNameForInterface):
+        (GetGnuMangledNameForInterface):
+        (GetWinVTableNameForInterface):
+        (GetWinMangledNameForInterface):
+        Strength-reduce GetNativeTypeForConversions and GetNamespaceForInterface into their callers.
+
+        (GetBaseIDLType):
+        Add support for IDLRecord. Remove call to GetIDLInterfaceName now that is simply the type name.
+
+        (GetNativeType):
+        Simplify sequence/FrozenArray support and add record support.
+
+        (GetNativeInnerType):
+        Generalize GetNativeVectorInnerType to work for record types as well.
+
+        (ShouldPassWrapperByReference):
+        Moved so native type accessors can be together.
+
+        (NativeToJSValueDOMConvertNeedsState):
+        (NativeToJSValueDOMConvertNeedsGlobalObject):
+        Add record support.
+
+        (GetNativeTypeForConversions): Deleted.
+        (GetNamespaceForInterface): Deleted.
+        (GetNativeVectorType): Deleted.
+        (GetIDLInterfaceName): Deleted.
+        (GetNativeVectorInnerType): Deleted.
+        Remove unneeded functions.
+
+        * bindings/scripts/IDLParser.pm:
+        (typeDescription):
+        Add helper useful for debugging, that constructs the string form of a type.
+
+        (typeByApplyingTypedefs):
+        Add missing call to typeByApplyingTypedefs (this is noted by a fix in JSTestCallbackFunctionWithTypedefs.h)
+
+        (parseNonAnyType):
+        Remove unused $subtypeName variables and add support for parsing record types.
+
+        * bindings/scripts/test/JS/JSTestCallbackFunctionWithTypedefs.cpp:
+        * bindings/scripts/test/JS/JSTestCallbackFunctionWithTypedefs.h:
+        * bindings/scripts/test/JS/JSTestObj.cpp:
+        * bindings/scripts/test/TestObj.idl:
+        Add tests for records and update results.
+
+        * testing/TypeConversions.h:
+        (WebCore::TypeConversions::testLongRecord):
+        (WebCore::TypeConversions::setTestLongRecord):
+        (WebCore::TypeConversions::testNodeRecord):
+        (WebCore::TypeConversions::setTestNodeRecord):
+        (WebCore::TypeConversions::testSequenceRecord):
+        (WebCore::TypeConversions::setTestSequenceRecord):
+        * testing/TypeConversions.idl:
+        Add record types so it can be tested from layout tests.
+
 2016-11-18  Dave Hyatt  <[email protected]>
 
         [CSS Parser] Support font-variation-settings

Modified: trunk/Source/WebCore/bindings/generic/IDLTypes.h (208892 => 208893)


--- trunk/Source/WebCore/bindings/generic/IDLTypes.h	2016-11-18 21:41:40 UTC (rev 208892)
+++ trunk/Source/WebCore/bindings/generic/IDLTypes.h	2016-11-18 21:47:42 UTC (rev 208893)
@@ -26,6 +26,7 @@
 #pragma once
 
 #include <wtf/Brigand.h>
+#include <wtf/HashMap.h>
 #include <wtf/StdLibExtras.h>
 #include <wtf/text/WTFString.h>
 
@@ -116,11 +117,15 @@
     using InnerType = T;
 };
 
+template<typename K, typename V> struct IDLRecord : IDLType<HashMap<typename K::ImplementationType, typename V::ImplementationType>> {
+    using KeyType = K;
+    using ValueType = V;
+};
+
 template<typename T> struct IDLPromise : IDLType<DOMPromise<T>> {
     using InnerType = T;
 };
 
-struct IDLRegExp : IDLUnsupportedType { };
 struct IDLError : IDLUnsupportedType { };
 struct IDLDOMException : IDLUnsupportedType { };
 
@@ -158,6 +163,9 @@
 struct IsIDLFrozenArray : public std::integral_constant<bool, WTF::IsTemplate<T, IDLFrozenArray>::value> { };
 
 template<typename T>
+struct IsIDLRecord : public std::integral_constant<bool, WTF::IsTemplate<T, IDLRecord>::value> { };
+
+template<typename T>
 struct IsIDLNumber : public std::integral_constant<bool, WTF::IsBaseOfTemplate<IDLNumber, T>::value> { };
 
 template<typename T>

Modified: trunk/Source/WebCore/bindings/js/JSDOMBinding.cpp (208892 => 208893)


--- trunk/Source/WebCore/bindings/js/JSDOMBinding.cpp	2016-11-18 21:41:40 UTC (rev 208892)
+++ trunk/Source/WebCore/bindings/js/JSDOMBinding.cpp	2016-11-18 21:47:42 UTC (rev 208893)
@@ -90,35 +90,26 @@
     return jsStringWithCache(exec, url.string());
 }
 
-static inline bool hasUnpairedSurrogate(StringView string)
+static inline String stringToByteString(ExecState& state, JSC::ThrowScope& scope, String&& string)
 {
-    // Fast path for 8-bit strings; they can't have any surrogates.
-    if (string.is8Bit())
-        return false;
-    for (auto codePoint : string.codePoints()) {
-        if (U_IS_SURROGATE(codePoint))
-            return true;
+    if (!string.containsOnlyLatin1()) {
+        throwTypeError(&state, scope);
+        return { };
     }
-    return false;
+
+    return string;
 }
 
-String valueToByteString(ExecState& state, JSValue value)
+String identifierToByteString(ExecState& state, const Identifier& identifier)
 {
     VM& vm = state.vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
 
-    String string = value.toWTFString(&state);
-    RETURN_IF_EXCEPTION(scope, { });
-
-    if (!string.containsOnlyLatin1()) {
-        throwTypeError(&state, scope);
-        return { };
-    }
-
-    return string;
+    String string = identifier.string();
+    return stringToByteString(state, scope, WTFMove(string));
 }
 
-String valueToUSVString(ExecState& state, JSValue value)
+String valueToByteString(ExecState& state, JSValue value)
 {
     VM& vm = state.vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
@@ -126,6 +117,23 @@
     String string = value.toWTFString(&state);
     RETURN_IF_EXCEPTION(scope, { });
 
+    return stringToByteString(state, scope, WTFMove(string));
+}
+
+static inline bool hasUnpairedSurrogate(StringView string)
+{
+    // Fast path for 8-bit strings; they can't have any surrogates.
+    if (string.is8Bit())
+        return false;
+    for (auto codePoint : string.codePoints()) {
+        if (U_IS_SURROGATE(codePoint))
+            return true;
+    }
+    return false;
+}
+
+static inline String stringToUSVString(String&& string)
+{
     // Fast path for the case where there are no unpaired surrogates.
     if (!hasUnpairedSurrogate(string))
         return string;
@@ -144,6 +152,23 @@
     return result.toString();
 }
 
+String identifierToUSVString(ExecState&, const Identifier& identifier)
+{
+    String string = identifier.string();
+    return stringToUSVString(WTFMove(string));
+}
+
+String valueToUSVString(ExecState& state, JSValue value)
+{
+    VM& vm = state.vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    String string = value.toWTFString(&state);
+    RETURN_IF_EXCEPTION(scope, { });
+
+    return stringToUSVString(WTFMove(string));
+}
+
 JSValue jsDate(ExecState* exec, double value)
 {
     return DateInstance::create(exec->vm(), exec->lexicalGlobalObject()->dateStructure(), value);

Modified: trunk/Source/WebCore/bindings/js/JSDOMBinding.h (208892 => 208893)


--- trunk/Source/WebCore/bindings/js/JSDOMBinding.h	2016-11-18 21:41:40 UTC (rev 208892)
+++ trunk/Source/WebCore/bindings/js/JSDOMBinding.h	2016-11-18 21:47:42 UTC (rev 208893)
@@ -215,7 +215,9 @@
 
 AtomicString propertyNameToAtomicString(JSC::PropertyName);
 
+WEBCORE_EXPORT String identifierToByteString(JSC::ExecState&, const JSC::Identifier&);
 WEBCORE_EXPORT String valueToByteString(JSC::ExecState&, JSC::JSValue);
+WEBCORE_EXPORT String identifierToUSVString(JSC::ExecState&, const JSC::Identifier&);
 WEBCORE_EXPORT String valueToUSVString(JSC::ExecState&, JSC::JSValue);
 
 int32_t finiteInt32Value(JSC::JSValue, JSC::ExecState*, bool& okay);

Modified: trunk/Source/WebCore/bindings/js/JSDOMConvert.h (208892 => 208893)


--- trunk/Source/WebCore/bindings/js/JSDOMConvert.h	2016-11-18 21:41:40 UTC (rev 208892)
+++ trunk/Source/WebCore/bindings/js/JSDOMConvert.h	2016-11-18 21:47:42 UTC (rev 208893)
@@ -856,6 +856,137 @@
 };
 
 // MARK: -
+// MARK: Record type
+
+namespace Detail {
+    template<typename IDLStringType>
+    struct IdentifierConverter;
+
+    template<> struct IdentifierConverter<IDLDOMString> {
+        static String convert(JSC::ExecState&, const JSC::Identifier& identifier)
+        {
+            return identifier.string();
+        }
+    };
+
+    template<> struct IdentifierConverter<IDLByteString> {
+        static String convert(JSC::ExecState& state, const JSC::Identifier& identifier)
+        {
+            return identifierToByteString(state, identifier);
+        }
+    };
+
+    template<> struct IdentifierConverter<IDLUSVString> {
+        static String convert(JSC::ExecState& state, const JSC::Identifier& identifier)
+        {
+            return identifierToUSVString(state, identifier);
+        }
+    };
+}
+
+template<typename K, typename V> struct Converter<IDLRecord<K, V>> : DefaultConverter<IDLRecord<K, V>> {
+    using ReturnType = typename IDLRecord<K, V>::ImplementationType;
+    using KeyType = typename K::ImplementationType;
+    using ValueType = typename V::ImplementationType;
+
+    static ReturnType convert(JSC::ExecState& state, JSC::JSValue value)
+    {
+        auto& vm = state.vm();
+        auto scope = DECLARE_THROW_SCOPE(vm);
+
+        // 1. Let result be a new empty instance of record<K, V>.
+        // 2. If Type(O) is Undefined or Null, return result.
+        if (value.isUndefinedOrNull())
+            return { };
+        
+        // 3. If Type(O) is not Object, throw a TypeError.
+        if (!value.isObject()) {
+            throwTypeError(&state, scope);
+            return { };
+        }
+        
+        JSC::JSObject* object = JSC::asObject(value);
+    
+        ReturnType result;
+    
+        // 4. Let keys be ? O.[[OwnPropertyKeys]]().
+        JSC::PropertyNameArray keys(&vm, JSC::PropertyNameMode::Strings);
+        object->getOwnPropertyNames(object, &state, keys, JSC::EnumerationMode());
+        RETURN_IF_EXCEPTION(scope, { });
+
+        // 5. Repeat, for each element key of keys in List order:
+        for (auto& key : keys) {
+            // 1. Let desc be ? O.[[GetOwnProperty]](key).
+            JSC::PropertyDescriptor descriptor;
+            bool didGetDescriptor = object->getOwnPropertyDescriptor(&state, key, descriptor);
+            RETURN_IF_EXCEPTION(scope, { });
+
+            if (!didGetDescriptor)
+                continue;
+
+            // 2. If desc is not undefined and desc.[[Enumerable]] is true:
+            
+            // FIXME: Do we need to check for enumerable / undefined, or is this handled by the default
+            // enumeration mode?
+
+            if (!descriptor.value().isUndefined() && descriptor.enumerable()) {
+                // 1. Let typedKey be key converted to an IDL value of type K.
+                auto typedKey = Detail::IdentifierConverter<K>::convert(state, key);
+
+                // 2. Let value be ? Get(O, key).
+                auto subValue = object->get(&state, key);
+                RETURN_IF_EXCEPTION(scope, { });
+
+                // 3. Let typedValue be value converted to an IDL value of type V.
+                auto typedValue = Converter<V>::convert(state, subValue);
+                RETURN_IF_EXCEPTION(scope, { });
+                
+                // 4. If typedKey is already a key in result, set its value to typedValue.
+                // Note: This can happen when O is a proxy object.
+                // 5. Otherwise, append to result a mapping (typedKey, typedValue).
+                result.set(typedKey, typedValue);
+            }
+        }
+
+        // 6. Return result.
+        return result;
+    }
+};
+
+template<typename K, typename V> struct JSConverter<IDLRecord<K, V>> {
+    static constexpr bool needsState = true;
+    static constexpr bool needsGlobalObject = true;
+
+    template<typename ValueType>
+    static JSC::JSValue convert(JSC::ExecState& state, JSDOMGlobalObject& globalObject, const HashMap<String, ValueType>& map)
+    {
+        auto& vm = state.vm();
+    
+        // 1. Let result be ! ObjectCreate(%ObjectPrototype%).
+        auto result = constructEmptyObject(&state);
+        
+        // 2. Repeat, for each mapping (key, value) in D:
+        for (const auto& keyValuePair : map) {
+            // 1. Let esKey be key converted to an ECMAScript value.
+            // Note, this step is not required, as we need the key to be
+            // an Identifier, not a JSValue.
+
+            // 2. Let esValue be value converted to an ECMAScript value.
+            auto esValue = toJS<V>(state, globalObject, keyValuePair.value);
+
+            // 3. Let created be ! CreateDataProperty(result, esKey, esValue).
+            bool created = result->putDirect(vm, JSC::Identifier::fromString(&vm, keyValuePair.key), esValue);
+
+            // 4. Assert: created is true.
+            ASSERT_UNUSED(created, created);
+        }
+
+        // 3. Return result.
+        return result;
+    }
+};
+
+// MARK: -
 // MARK: Dictionary type
 
 template<typename T> struct Converter<IDLDictionary<T>> : DefaultConverter<IDLDictionary<T>> {
@@ -958,10 +1089,17 @@
     using DictionaryTypeList = brigand::filter<TypeList, IsIDLDictionary<brigand::_1>>;
     static constexpr size_t numberOfDictionaryTypes = brigand::size<DictionaryTypeList>::value;
     static_assert(numberOfDictionaryTypes == 0 || numberOfDictionaryTypes == 1, "There can be 0 or 1 dictionary types in an IDLUnion.");
-    using DictionaryType = ConditionalFront<DictionaryTypeList, numberOfDictionaryTypes != 0>;
+    static constexpr bool hasDictionaryType = numberOfDictionaryTypes != 0;
+    using DictionaryType = ConditionalFront<DictionaryTypeList, hasDictionaryType>;
 
-    static constexpr bool hasObjectType = (numberOfSequenceTypes + numberOfFrozenArrayTypes + numberOfDictionaryTypes) > 0;
+    using RecordTypeList = brigand::filter<TypeList, IsIDLRecord<brigand::_1>>;
+    static constexpr size_t numberOfRecordTypes = brigand::size<RecordTypeList>::value;
+    static_assert(numberOfRecordTypes == 0 || numberOfRecordTypes == 1, "There can be 0 or 1 record types in an IDLUnion.");
+    static constexpr bool hasRecordType = numberOfRecordTypes != 0;
+    using RecordType = ConditionalFront<RecordTypeList, hasRecordType>;
 
+    static constexpr bool hasObjectType = (numberOfSequenceTypes + numberOfFrozenArrayTypes + numberOfDictionaryTypes + numberOfRecordTypes) > 0;
+
     using InterfaceTypeList = brigand::filter<TypeList, IsIDLInterface<brigand::_1>>;
 
     static ReturnType convert(JSC::ExecState& state, JSC::JSValue value)
@@ -978,11 +1116,17 @@
         // 2. Let types be the flattened member types of the union type.
         // NOTE: Union is expected to be pre-flattented.
         
-        // 3. If V is null or undefined, and types includes a dictionary type, then return the result of converting V to that dictionary type.
-        constexpr bool hasDictionaryType = numberOfDictionaryTypes != 0;
-        if (hasDictionaryType) {
-            if (value.isUndefinedOrNull())
-                return std::move<WTF::CheckMoveParameter>(ConditionalConverter<ReturnType, DictionaryType, hasDictionaryType>::convert(state, value).value());
+        // 3. If V is null or undefined then:
+        if (hasDictionaryType || hasRecordType) {
+            if (value.isUndefinedOrNull()) {
+                //     1. If types includes a dictionary type, then return the result of converting V to that dictionary type.
+                if (hasDictionaryType)
+                    return std::move<WTF::CheckMoveParameter>(ConditionalConverter<ReturnType, DictionaryType, hasDictionaryType>::convert(state, value).value());
+                
+                //     2. If types includes a record type, then return the result of converting V to that record type.
+                if (hasRecordType)
+                    return std::move<WTF::CheckMoveParameter>(ConditionalConverter<ReturnType, RecordType, hasRecordType>::convert(state, value).value());
+            }
         }
 
         // 4. If V is a platform object, then:
@@ -1011,13 +1155,13 @@
                 return WTFMove(returnValue.value());
         }
         
-        // FIXME: Add support for steps 5 - 11.
+        // FIXME: Add support for steps 5 - 10.
 
-        // 12. If V is any kind of object except for a native RegExp object, then:
+        // 11. If V is any kind of object, then:
         if (hasObjectType) {
             if (value.isCell()) {
                 JSC::JSCell* cell = value.asCell();
-                if (cell->isObject() && cell->type() != JSC::RegExpObjectType) {
+                if (cell->isObject()) {
                     // FIXME: We should be able to optimize the following code by making use
                     // of the fact that we have proved that the value is an object. 
                 
@@ -1053,7 +1197,9 @@
                         return std::move<WTF::CheckMoveParameter>(ConditionalConverter<ReturnType, DictionaryType, hasDictionaryType>::convert(state, value).value());
 
                     //     4. If types includes a record type, then return the result of converting V to that record type.
-                    //         (FIXME: Add support for record types and step 12.4)
+                    if (hasRecordType)
+                        return std::move<WTF::CheckMoveParameter>(ConditionalConverter<ReturnType, RecordType, hasRecordType>::convert(state, value).value());
+
                     //     5. If types includes a callback interface type, then return the result of converting V to that interface type.
                     //         (FIXME: Add support for callback interface type and step 12.5)
                     //     6. If types includes object, then return the IDL value that is a reference to the object V.
@@ -1062,7 +1208,7 @@
             }
         }
 
-        // 13. If V is a Boolean value, then:
+        // 12. If V is a Boolean value, then:
         //     1. If types includes a boolean, then return the result of converting V to boolean.
         constexpr bool hasBooleanType = brigand::any<TypeList, std::is_same<IDLBoolean, brigand::_1>>::value;
         if (hasBooleanType) {
@@ -1070,7 +1216,7 @@
                 return std::move<WTF::CheckMoveParameter>(ConditionalConverter<ReturnType, IDLBoolean, hasBooleanType>::convert(state, value).value());
         }
         
-        // 14. If V is a Number value, then:
+        // 13. If V is a Number value, then:
         //     1. If types includes a numeric type, then return the result of converting V to that numeric type.
         constexpr bool hasNumericType = brigand::size<NumericTypeList>::value != 0;
         if (hasNumericType) {
@@ -1078,20 +1224,20 @@
                 return std::move<WTF::CheckMoveParameter>(ConditionalConverter<ReturnType, NumericType, hasNumericType>::convert(state, value).value());
         }
         
-        // 15. If types includes a string type, then return the result of converting V to that type.
+        // 14. If types includes a string type, then return the result of converting V to that type.
         constexpr bool hasStringType = brigand::size<StringTypeList>::value != 0;
         if (hasStringType)
             return std::move<WTF::CheckMoveParameter>(ConditionalConverter<ReturnType, StringType, hasStringType>::convert(state, value).value());
 
-        // 16. If types includes a numeric type, then return the result of converting V to that numeric type.
+        // 15. If types includes a numeric type, then return the result of converting V to that numeric type.
         if (hasNumericType)
             return std::move<WTF::CheckMoveParameter>(ConditionalConverter<ReturnType, NumericType, hasNumericType>::convert(state, value).value());
 
-        // 17. If types includes a boolean, then return the result of converting V to boolean.
+        // 16. If types includes a boolean, then return the result of converting V to boolean.
         if (hasBooleanType)
             return std::move<WTF::CheckMoveParameter>(ConditionalConverter<ReturnType, IDLBoolean, hasBooleanType>::convert(state, value).value());
 
-        // 18. Throw a TypeError.
+        // 17. Throw a TypeError.
         throwTypeError(&state, scope);
         return ReturnType();
     }

Modified: trunk/Source/WebCore/bindings/scripts/CodeGenerator.pm (208892 => 208893)


--- trunk/Source/WebCore/bindings/scripts/CodeGenerator.pm	2016-11-18 21:41:40 UTC (rev 208892)
+++ trunk/Source/WebCore/bindings/scripts/CodeGenerator.pm	2016-11-18 21:47:42 UTC (rev 208893)
@@ -352,23 +352,6 @@
 
 # Helpers for all CodeGenerator***.pm modules
 
-sub SkipIncludeHeader
-{
-    my ($object, $typeName) = @_;
-
-    # FIXME: This is a lot like !IsRefPtrType. Maybe they could share code?
-
-    return 1 if $primitiveTypeHash{$typeName};
-    return 1 if $integerTypeHash{$typeName};
-    return 1 if $floatingPointTypeHash{$typeName};
-    return 1 if $typedArrayTypes{$typeName};
-    return 1 if $stringTypeHash{$typeName};
-    return 1 if $typeName eq "BufferSource";
-    return 1 if $typeName eq "any";
-
-    return 0;
-}
-
 sub IsNumericType
 {
     my ($object, $type) = @_;
@@ -616,7 +599,9 @@
     return 0 if $object->IsDictionaryType($type);
     return 0 if $object->IsEnumType($type);
     return 0 if $object->IsSequenceOrFrozenArrayType($type);
+    return 0 if $object->IsRecordType($type);
     return 0 if $object->IsStringType($type);
+    return 0 if $type->isUnion;
     return 0 if $type->name eq "any";
 
     return 1;
@@ -656,15 +641,6 @@
     return $type->name eq "sequence";
 }
 
-sub GetSequenceInnerType
-{
-    my ($object, $type) = @_;
-
-    assert("Not a type") if ref($type) ne "IDLType";
-
-    return @{$type->subtypes}[0];
-}
-
 sub IsFrozenArrayType
 {
     my ($object, $type) = @_;
@@ -674,15 +650,6 @@
     return $type->name eq "FrozenArray";
 }
 
-sub GetFrozenArrayInnerType
-{
-    my ($object, $type) = @_;
-
-    assert("Not a type") if ref($type) ne "IDLType";
-
-    return @{$type->subtypes}[0];
-}
-
 sub IsSequenceOrFrozenArrayType
 {
     my ($object, $type) = @_;
@@ -692,13 +659,13 @@
     return $object->IsSequenceType($type) || $object->IsFrozenArrayType($type);
 }
 
-sub GetSequenceOrFrozenArrayInnerType
+sub IsRecordType
 {
     my ($object, $type) = @_;
 
     assert("Not a type") if ref($type) ne "IDLType";
 
-    return @{$type->subtypes}[0];
+    return $type->name eq "record";
 }
 
 # These match WK_lcfirst and WK_ucfirst defined in builtins_generator.py.
@@ -897,7 +864,6 @@
     return 0 if !$object->IsRefPtrType($type);
     return 0 if $object->IsTypedArrayType($type);
     return 0 if $type->name eq "BufferSource";
-    return 0 if $type->name eq "UNION";
     return 0 if $webCoreTypeHash{$type->name};
 
     return 1;

Modified: trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm (208892 => 208893)


--- trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm	2016-11-18 21:41:40 UTC (rev 208892)
+++ trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm	2016-11-18 21:47:42 UTC (rev 208893)
@@ -261,8 +261,6 @@
 {
     my ($implementationType, $includesRef) = @_;
 
-    return if $codeGenerator->SkipIncludeHeader($implementationType);
-
     $includesRef->{"${implementationType}.h"} = 1;
 }
 
@@ -299,20 +297,22 @@
         return;
     }
 
+    if ($codeGenerator->IsRecordType($type)) {
+        AddToIncludes("<wtf/HashMap.h>", $includesRef, $conditional);
+        AddToIncludesForIDLType(@{$type->subtypes}[0], $includesRef, $conditional);
+        AddToIncludesForIDLType(@{$type->subtypes}[1], $includesRef, $conditional);
+        return;
+    }
+
     if ($codeGenerator->IsWrapperType($type) || $codeGenerator->IsExternalDictionaryType($type) || $codeGenerator->IsExternalEnumType($type)) {
         AddToIncludes("JS" . $type->name . ".h", $includesRef, $conditional);
         return;
     }
     
-    if ($type->name eq "SerializedScriptValue") {
-        AddToIncludes("SerializedScriptValue.h", $includesRef, $conditional);
+    if ($type->name eq "SerializedScriptValue" || $type->name eq "Dictionary") {
+        AddToIncludes($type->name . ".h", $includesRef, $conditional);
         return;
     }
-
-    if ($type->name eq "Dictionary") {
-        AddToIncludes("Dictionary.h", $includesRef, $conditional);
-        return;
-    }
 }
 
 sub AddToImplIncludes
@@ -2169,20 +2169,20 @@
         my ($type, $optionality) = @_;
         return $optionality eq "optional";
     };
-    my $isDictionaryParameter = sub {
+    my $isDictionaryOrRecordParameter = sub {
         my ($type, $optionality) = @_;
-        return $type->name eq "Dictionary" || $codeGenerator->IsDictionaryType($type);
+        return $type->name eq "Dictionary" || $codeGenerator->IsDictionaryType($type) || $codeGenerator->IsRecordType($type);
     };
-    my $isNullableOrDictionaryParameterOrUnionContainingOne = sub {
+    my $isNullableOrDictionaryOrRecordOrUnionContainingOne = sub {
         my ($type, $optionality) = @_;
         return 1 if $type->isNullable;
         if ($type->isUnion) {
             for my $subtype (GetFlattenedMemberTypes($type)) {
-                return 1 if $type->isNullable || &$isDictionaryParameter($subtype, $optionality);
+                return 1 if $type->isNullable || &$isDictionaryOrRecordParameter($subtype, $optionality);
             }
             return 0;
         } else {
-            return &$isDictionaryParameter($type, $optionality);
+            return &$isDictionaryOrRecordParameter($type, $optionality);
         }
     };
     my $isRegExpOrObjectParameter = sub {
@@ -2206,9 +2206,9 @@
         my ($type, $optionality) = @_;
         return $codeGenerator->IsSequenceOrFrozenArrayType($type);
     };
-    my $isDictionaryOrObjectOrCallbackInterfaceParameter = sub {
+    my $isDictionaryOrRecordOrObjectOrCallbackInterfaceParameter = sub {
         my ($type, $optionality) = @_;
-        return 1 if &$isDictionaryParameter($type, $optionality);
+        return 1 if &$isDictionaryOrRecordParameter($type, $optionality);
         return 1 if $type->name eq "object";
         return 1 if $codeGenerator->IsCallbackInterface($type) && !$codeGenerator->IsCallbackFunction($type);
         return 0;
@@ -2260,7 +2260,7 @@
             my $overload = GetOverloadThatMatchesIgnoringUnionSubtypes($S, $d, \&$isOptionalParameter);
             &$generateOverloadCallIfNecessary($overload, "distinguishingArg.isUndefined()");
 
-            $overload = GetOverloadThatMatchesIgnoringUnionSubtypes($S, $d, \&$isNullableOrDictionaryParameterOrUnionContainingOne);
+            $overload = GetOverloadThatMatchesIgnoringUnionSubtypes($S, $d, \&$isNullableOrDictionaryOrRecordOrUnionContainingOne);
             &$generateOverloadCallIfNecessary($overload, "distinguishingArg.isUndefinedOrNull()");
 
             for my $tuple (@{$S}) {
@@ -2296,7 +2296,7 @@
             $overload = GetOverloadThatMatches($S, $d, \&$isSequenceOrFrozenArrayParameter);
             &$generateOverloadCallIfNecessary($overload, "hasIteratorMethod(*state, distinguishingArg)");
 
-            $overload = GetOverloadThatMatches($S, $d, \&$isDictionaryOrObjectOrCallbackInterfaceParameter);
+            $overload = GetOverloadThatMatches($S, $d, \&$isDictionaryOrRecordOrObjectOrCallbackInterfaceParameter);
             &$generateOverloadCallIfNecessary($overload, "distinguishingArg.isObject() && asObject(distinguishingArg)->type() != RegExpObjectType");
 
             my $booleanOverload = GetOverloadThatMatches($S, $d, \&$isBooleanParameter);
@@ -2372,13 +2372,6 @@
     return $result;
 }
 
-sub GetNativeTypeForConversions
-{
-    my $interface = shift;
-
-    return $interface->type->name;
-}
-
 # See http://refspecs.linux-foundation.org/cxxabi-1.83.html.
 sub GetGnuVTableRefForInterface
 {
@@ -2387,7 +2380,7 @@
     if (!$vtableName) {
         return "0";
     }
-    my $typename = GetNativeTypeForConversions($interface);
+    my $typename = $interface->type->name;
     my $offset = GetGnuVTableOffsetForType($typename);
     return "&" . $vtableName . "[" . $offset . "]";
 }
@@ -2395,7 +2388,7 @@
 sub GetGnuVTableNameForInterface
 {
     my $interface = shift;
-    my $typename = GetNativeTypeForConversions($interface);
+    my $typename = $interface->type->name;
     my $templatePosition = index($typename, "<");
     return "" if $templatePosition != -1;
     return "" if GetImplementationLacksVTableForInterface($interface);
@@ -2406,13 +2399,13 @@
 sub GetGnuMangledNameForInterface
 {
     my $interface = shift;
-    my $typename = GetNativeTypeForConversions($interface);
+    my $typename = $interface->type->name;
     my $templatePosition = index($typename, "<");
     if ($templatePosition != -1) {
         return "";
     }
     my $mangledType = length($typename) . $typename;
-    my $namespace = GetNamespaceForInterface($interface);
+    my $namespace = "WebCore";
     my $mangledNamespace =  "N" . length($namespace) . $namespace;
     return $mangledNamespace . $mangledType . "E";
 }
@@ -2456,7 +2449,7 @@
 sub GetWinVTableNameForInterface
 {
     my $interface = shift;
-    my $typename = GetNativeTypeForConversions($interface);
+    my $typename = $interface->type->name;
     my $templatePosition = index($typename, "<");
     return "" if $templatePosition != -1;
     return "" if GetImplementationLacksVTableForInterface($interface);
@@ -2467,17 +2460,11 @@
 sub GetWinMangledNameForInterface
 {
     my $interface = shift;
-    my $typename = GetNativeTypeForConversions($interface);
-    my $namespace = GetNamespaceForInterface($interface);
+    my $typename = $interface->type->name;
+    my $namespace = "WebCore";
     return $typename . "@" . $namespace . "@@";
 }
 
-sub GetNamespaceForInterface
-{
-    my $interface = shift;
-    return "WebCore";
-}
-
 sub GetImplementationLacksVTableForInterface
 {
     my $interface = shift;
@@ -5054,6 +5041,7 @@
 }
 
 my %nativeType = (
+    "ByteString" => "String",
     "DOMString" => "String",
     "USVString" => "String",
     "Date" => "double",
@@ -5077,16 +5065,6 @@
     "unsigned short" => "uint16_t",
 );
 
-sub GetNativeVectorType
-{
-    my ($type) = @_;
-
-    die "This should only be called for sequence or array types" unless $codeGenerator->IsSequenceOrFrozenArrayType($type);
-
-    my $innerType = $codeGenerator->GetSequenceOrFrozenArrayInnerType($type);
-    return "Vector<" . GetNativeVectorInnerType($innerType) . ">";
-}
-
 # http://heycam.github.io/webidl/#dfn-flattened-union-member-types
 sub GetFlattenedMemberTypes
 {
@@ -5138,13 +5116,6 @@
     return @idlUnionMemberTypes;
 }
 
-sub GetIDLInterfaceName
-{
-    my ($type) = @_;
-
-    return $type->name;
-}
-
 sub GetBaseIDLType
 {
     my ($interface, $type) = @_;
@@ -5178,8 +5149,9 @@
     return "IDLDictionary<" . GetDictionaryClassName($type, $interface) . ">" if $codeGenerator->IsDictionaryType($type);
     return "IDLSequence<" . GetIDLType($interface, @{$type->subtypes}[0]) . ">" if $codeGenerator->IsSequenceType($type);
     return "IDLFrozenArray<" . GetIDLType($interface, @{$type->subtypes}[0]) . ">" if $codeGenerator->IsFrozenArrayType($type);
+    return "IDLRecord<" . GetIDLType($interface, @{$type->subtypes}[0]) . ", " . GetIDLType($interface, @{$type->subtypes}[1]) . ">" if $codeGenerator->IsRecordType($type);
     return "IDLUnion<" . join(", ", GetIDLUnionMemberTypes($interface, $type)) . ">" if $type->isUnion;
-    return "IDLInterface<" . GetIDLInterfaceName($type) . ">";
+    return "IDLInterface<" . $type->name . ">";
 }
 
 sub GetIDLType
@@ -5203,30 +5175,25 @@
 
     return GetEnumerationClassName($type, $interface) if $codeGenerator->IsEnumType($type);
     return GetDictionaryClassName($type, $interface) if $codeGenerator->IsDictionaryType($type);
-    return GetNativeVectorType($type) if $codeGenerator->IsSequenceOrFrozenArrayType($type);
+    return "Vector<" . GetNativeInnerType(@{$type->subtypes}[0], $interface) . ">" if $codeGenerator->IsSequenceOrFrozenArrayType($type);
+    return "HashMap<" . GetNativeInnerType(@{$type->subtypes}[0], $interface) . ", " . GetNativeInnerType(@{$type->subtypes}[1], $interface) . ">" if $codeGenerator->IsRecordType($type);
 
     return "RefPtr<${typeName}>" if $codeGenerator->IsTypedArrayType($type) and $typeName ne "ArrayBuffer";
     return "${typeName}*";
 }
 
-sub ShouldPassWrapperByReference
+sub GetNativeInnerType
 {
-    my ($parameter, $interface) = @_;
+    my ($innerType, $interface) = @_;
 
-    return 0 if $codeGenerator->IsCallbackInterface($parameter->type) || $codeGenerator->IsCallbackFunction($parameter->type);
-
-    my $nativeType = GetNativeType($interface, $parameter->type);
-    return $codeGenerator->ShouldPassWrapperByReference($parameter) && (substr($nativeType, -1) eq '*' || $nativeType =~ /^RefPtr/);
-}
-
-sub GetNativeVectorInnerType
-{
-    my $innerType = shift;
-
     my $innerTypeName = $innerType->name;
 
     return $nativeType{$innerTypeName} if exists $nativeType{$innerTypeName};
-    return GetDictionaryClassName($innerType) if $codeGenerator->IsDictionaryType($innerType);
+
+    return GetEnumerationClassName($innerType, $interface) if $codeGenerator->IsEnumType($innerType);
+    return GetDictionaryClassName($innerType, $interface) if $codeGenerator->IsDictionaryType($innerType);
+    return "Vector<" . GetNativeInnerType(@{$innerType->subtypes}[0], $interface) . ">" if $codeGenerator->IsSequenceOrFrozenArrayType($innerType);
+    return "HashMap<" . GetNativeInnerType(@{$innerType->subtypes}[0], $interface) . ", " . GetNativeInnerType(@{$innerType->subtypes}[1], $interface) . ">" if $codeGenerator->IsRecordType($innerType);
     return "RefPtr<$innerTypeName>";
 }
 
@@ -5246,6 +5213,16 @@
     return GetNativeType($interface, $type);
 }
 
+sub ShouldPassWrapperByReference
+{
+    my ($parameter, $interface) = @_;
+
+    return 0 if $codeGenerator->IsCallbackInterface($parameter->type) || $codeGenerator->IsCallbackFunction($parameter->type);
+
+    my $nativeType = GetNativeType($interface, $parameter->type);
+    return $codeGenerator->ShouldPassWrapperByReference($parameter) && (substr($nativeType, -1) eq '*' || $nativeType =~ /^RefPtr/);
+}
+
 sub GetIntegerConversionConfiguration
 {
     my $context = shift;
@@ -5375,6 +5352,7 @@
     # FIXME: This should actually check if all the sub-objects of the union need the state.
     return 1 if $type->isUnion;
     return 1 if $codeGenerator->IsSequenceOrFrozenArrayType($type);
+    return 1 if $codeGenerator->IsRecordType($type);
     return 1 if $codeGenerator->IsStringType($type);
     return 1 if $codeGenerator->IsEnumType($type);
     return 1 if $codeGenerator->IsWrapperType($type);
@@ -5391,6 +5369,7 @@
     # FIXME: This should actually check if all the sub-objects of the union need the global object.
     return 1 if $type->isUnion;
     return 1 if $codeGenerator->IsSequenceOrFrozenArrayType($type);
+    return 1 if $codeGenerator->IsRecordType($type);
     return 1 if $codeGenerator->IsWrapperType($type);
     return 1 if $codeGenerator->IsTypedArrayType($type);
 
@@ -6029,7 +6008,6 @@
         push(@$outputArray, "\n");
     }
     push(@$outputArray, "template<> const ClassInfo ${constructorClassName}::s_info = { \"${visibleInterfaceName}\", &Base::s_info, 0, CREATE_METHOD_TABLE($constructorClassName) };\n\n");
- 
 }
 
 sub HasCustomConstructor

Modified: trunk/Source/WebCore/bindings/scripts/IDLParser.pm (208892 => 208893)


--- trunk/Source/WebCore/bindings/scripts/IDLParser.pm	2016-11-18 21:41:40 UTC (rev 208892)
+++ trunk/Source/WebCore/bindings/scripts/IDLParser.pm	2016-11-18 21:47:42 UTC (rev 208893)
@@ -383,6 +383,17 @@
     return $type;
 }
 
+sub typeDescription
+{
+    my $type = shift;
+
+    if (scalar @{$type->subtypes}) {
+        return $type->name . '<' . join(', ', map { typeDescription($_) } @{$type->subtypes}) . '>' . ($type->isNullable ? "?" : "");
+    }
+
+    return $type->name . ($type->isNullable ? "?" : "");
+}
+
 sub makeSimpleType
 {
     my $typeName = shift;
@@ -528,7 +539,7 @@
         my $clonedType = $self->cloneType($typedef->type);
         $clonedType->isNullable($clonedType->isNullable || $type->isNullable);
 
-        return $clonedType;
+        return $self->typeByApplyingTypedefs($clonedType);
     }
     
     return $type;
@@ -2101,7 +2112,6 @@
         $self->assertTokenValue($self->getToken(), "<", __LINE__);
 
         my $subtype = $self->parseType();
-        my $subtypeName = $subtype->name;
 
         $self->assertTokenValue($self->getToken(), ">", __LINE__);
 
@@ -2115,7 +2125,6 @@
         $self->assertTokenValue($self->getToken(), "<", __LINE__);
 
         my $subtype = $self->parseType();
-        my $subtypeName = $subtype->name;
 
         $self->assertTokenValue($self->getToken(), ">", __LINE__);
 
@@ -2129,7 +2138,6 @@
         $self->assertTokenValue($self->getToken(), "<", __LINE__);
 
         my $subtype = $self->parseReturnType();
-        my $subtypeName = $subtype->name;
 
         $self->assertTokenValue($self->getToken(), ">", __LINE__);
 
@@ -2138,6 +2146,25 @@
 
         return $type;
     }
+    if ($next->value() eq "record") {
+        $self->assertTokenValue($self->getToken(), "record", __LINE__);
+        $self->assertTokenValue($self->getToken(), "<", __LINE__);
+
+        my $keyType = IDLType->new();
+        $keyType->name($self->parseStringType());
+
+        $self->assertTokenValue($self->getToken(), ",", __LINE__);
+
+        my $valueType = $self->parseType();
+
+        $self->assertTokenValue($self->getToken(), ">", __LINE__);
+
+        $type->name("record");
+        push(@{$type->subtypes}, $keyType);
+        push(@{$type->subtypes}, $valueType);
+
+        return $type;
+    }
     if ($next->type() == IdentifierToken) {
         my $identifier = $self->getToken();
 

Modified: trunk/Source/WebCore/bindings/scripts/test/JS/JSTestCallbackFunctionWithTypedefs.cpp (208892 => 208893)


--- trunk/Source/WebCore/bindings/scripts/test/JS/JSTestCallbackFunctionWithTypedefs.cpp	2016-11-18 21:41:40 UTC (rev 208892)
+++ trunk/Source/WebCore/bindings/scripts/test/JS/JSTestCallbackFunctionWithTypedefs.cpp	2016-11-18 21:47:42 UTC (rev 208893)
@@ -22,7 +22,6 @@
 #include "JSTestCallbackFunctionWithTypedefs.h"
 
 #include "JSDOMConvert.h"
-#include "JSLONG.h"
 #include "ScriptExecutionContext.h"
 #include <runtime/JSArray.h>
 #include <runtime/JSLock.h>
@@ -52,7 +51,7 @@
 #endif
 }
 
-bool JSTestCallbackFunctionWithTypedefs::handleEvent(Vector<RefPtr<LONG>> sequenceArg, int32_t longArg)
+bool JSTestCallbackFunctionWithTypedefs::handleEvent(Vector<int32_t> sequenceArg, int32_t longArg)
 {
     if (!canInvokeCallback())
         return true;
@@ -63,7 +62,7 @@
 
     ExecState* state = m_data->globalObject()->globalExec();
     MarkedArgumentBuffer args;
-    args.append(toJS<IDLSequence<IDLNullable<IDLInterface<LONG>>>>(*state, *m_data->globalObject(), sequenceArg));
+    args.append(toJS<IDLSequence<IDLNullable<IDLLong>>>(*state, *m_data->globalObject(), sequenceArg));
     args.append(toJS<IDLLong>(longArg));
 
     NakedPtr<JSC::Exception> returnedException;

Modified: trunk/Source/WebCore/bindings/scripts/test/JS/JSTestCallbackFunctionWithTypedefs.h (208892 => 208893)


--- trunk/Source/WebCore/bindings/scripts/test/JS/JSTestCallbackFunctionWithTypedefs.h	2016-11-18 21:41:40 UTC (rev 208892)
+++ trunk/Source/WebCore/bindings/scripts/test/JS/JSTestCallbackFunctionWithTypedefs.h	2016-11-18 21:47:42 UTC (rev 208893)
@@ -40,7 +40,7 @@
     JSCallbackDataStrong* callbackData() { return m_data; }
 
     // Functions
-    virtual bool handleEvent(Vector<RefPtr<LONG>> sequenceArg, int32_t longArg);
+    virtual bool handleEvent(Vector<int32_t> sequenceArg, int32_t longArg);
 
 private:
     JSTestCallbackFunctionWithTypedefs(JSC::JSObject* callback, JSDOMGlobalObject*);

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


--- trunk/Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp	2016-11-18 21:41:40 UTC (rev 208892)
+++ trunk/Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp	2016-11-18 21:47:42 UTC (rev 208893)
@@ -66,6 +66,7 @@
 #include <runtime/ObjectConstructor.h>
 #include <runtime/PropertyNameArray.h>
 #include <wtf/GetPtr.h>
+#include <wtf/HashMap.h>
 #include <wtf/Variant.h>
 
 #if ENABLE(Condition1)
@@ -963,8 +964,12 @@
 JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionMethodWithUSVStringArg(JSC::ExecState*);
 JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionMethodWithNullableUSVStringArg(JSC::ExecState*);
 JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionMethodWithUSVStringArgTreatingNullAsEmptyString(JSC::ExecState*);
+JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionMethodWithByteStringArg(JSC::ExecState*);
+JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionMethodWithNullableByteStringArg(JSC::ExecState*);
+JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionMethodWithByteStringArgTreatingNullAsEmptyString(JSC::ExecState*);
 JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionSerializedValue(JSC::ExecState*);
 JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionOptionsObject(JSC::ExecState*);
+JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionMethodWithRecord(JSC::ExecState*);
 JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionMethodWithException(JSC::ExecState*);
 JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionMethodWithExceptionReturningLong(JSC::ExecState*);
 JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionMethodWithExceptionReturningObject(JSC::ExecState*);
@@ -1015,6 +1020,7 @@
 JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionMethodWithOptionalNullableWrapper(JSC::ExecState*);
 JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionMethodWithOptionalNullableWrapperIsNull(JSC::ExecState*);
 JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionMethodWithOptionalXPathNSResolver(JSC::ExecState*);
+JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionMethodWithOptionalRecord(JSC::ExecState*);
 JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionMethodWithCallbackArg(JSC::ExecState*);
 JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionMethodWithNonCallbackArgAndCallbackArg(JSC::ExecState*);
 JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionMethodWithCallbackAndOptionalArg(JSC::ExecState*);
@@ -1130,6 +1136,18 @@
 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 jsTestObjByteStringAttrTreatingNullAsEmptyString(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
+bool setJSTestObjByteStringAttrTreatingNullAsEmptyString(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);
+JSC::EncodedJSValue jsTestObjStringLongRecordAttr(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
+bool setJSTestObjStringLongRecordAttr(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);
+JSC::EncodedJSValue jsTestObjUsvstringLongRecordAttr(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
+bool setJSTestObjUsvstringLongRecordAttr(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);
+JSC::EncodedJSValue jsTestObjUsvstringLongRecordAttr(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
+bool setJSTestObjUsvstringLongRecordAttr(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);
+JSC::EncodedJSValue jsTestObjStringObjRecordAttr(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
+bool setJSTestObjStringObjRecordAttr(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);
+JSC::EncodedJSValue jsTestObjStringNullableObjRecordAttr(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
+bool setJSTestObjStringNullableObjRecordAttr(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);
@@ -1247,6 +1265,8 @@
 bool setJSTestObjNullableStringSettableAttribute(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);
 JSC::EncodedJSValue jsTestObjNullableUSVStringSettableAttribute(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
 bool setJSTestObjNullableUSVStringSettableAttribute(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);
+JSC::EncodedJSValue jsTestObjNullableByteStringSettableAttribute(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
+bool setJSTestObjNullableByteStringSettableAttribute(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);
 JSC::EncodedJSValue jsTestObjNullableStringValue(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
 bool setJSTestObjNullableStringValue(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);
 JSC::EncodedJSValue jsTestObjAttribute(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
@@ -1455,6 +1475,12 @@
     { "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) } },
+    { "byteStringAttrTreatingNullAsEmptyString", CustomAccessor, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjByteStringAttrTreatingNullAsEmptyString), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSTestObjByteStringAttrTreatingNullAsEmptyString) } },
+    { "stringLongRecordAttr", CustomAccessor, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjStringLongRecordAttr), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSTestObjStringLongRecordAttr) } },
+    { "usvstringLongRecordAttr", CustomAccessor, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjUsvstringLongRecordAttr), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSTestObjUsvstringLongRecordAttr) } },
+    { "usvstringLongRecordAttr", CustomAccessor, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjUsvstringLongRecordAttr), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSTestObjUsvstringLongRecordAttr) } },
+    { "stringObjRecordAttr", CustomAccessor, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjStringObjRecordAttr), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSTestObjStringObjRecordAttr) } },
+    { "stringNullableObjRecordAttr", CustomAccessor, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjStringNullableObjRecordAttr), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSTestObjStringNullableObjRecordAttr) } },
     { "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) } },
@@ -1534,6 +1560,7 @@
     { "nullableLongSettableAttribute", CustomAccessor, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjNullableLongSettableAttribute), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSTestObjNullableLongSettableAttribute) } },
     { "nullableStringSettableAttribute", CustomAccessor, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjNullableStringSettableAttribute), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSTestObjNullableStringSettableAttribute) } },
     { "nullableUSVStringSettableAttribute", CustomAccessor, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjNullableUSVStringSettableAttribute), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSTestObjNullableUSVStringSettableAttribute) } },
+    { "nullableByteStringSettableAttribute", CustomAccessor, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjNullableByteStringSettableAttribute), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSTestObjNullableByteStringSettableAttribute) } },
     { "nullableStringValue", CustomAccessor, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjNullableStringValue), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSTestObjNullableStringValue) } },
     { "attribute", ReadOnly | CustomAccessor, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjAttribute), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(0) } },
     { "attributeWithReservedEnumType", CustomAccessor, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjAttributeWithReservedEnumType), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSTestObjAttributeWithReservedEnumType) } },
@@ -1569,8 +1596,12 @@
     { "methodWithUSVStringArg", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionMethodWithUSVStringArg), (intptr_t) (1) } },
     { "methodWithNullableUSVStringArg", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionMethodWithNullableUSVStringArg), (intptr_t) (1) } },
     { "methodWithUSVStringArgTreatingNullAsEmptyString", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionMethodWithUSVStringArgTreatingNullAsEmptyString), (intptr_t) (1) } },
+    { "methodWithByteStringArg", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionMethodWithByteStringArg), (intptr_t) (1) } },
+    { "methodWithNullableByteStringArg", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionMethodWithNullableByteStringArg), (intptr_t) (1) } },
+    { "methodWithByteStringArgTreatingNullAsEmptyString", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionMethodWithByteStringArgTreatingNullAsEmptyString), (intptr_t) (1) } },
     { "serializedValue", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionSerializedValue), (intptr_t) (1) } },
     { "optionsObject", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionOptionsObject), (intptr_t) (1) } },
+    { "methodWithRecord", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionMethodWithRecord), (intptr_t) (1) } },
     { "methodWithException", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionMethodWithException), (intptr_t) (0) } },
     { "methodWithExceptionReturningLong", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionMethodWithExceptionReturningLong), (intptr_t) (0) } },
     { "methodWithExceptionReturningObject", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionMethodWithExceptionReturningObject), (intptr_t) (0) } },
@@ -1630,6 +1661,7 @@
     { "methodWithOptionalNullableWrapper", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionMethodWithOptionalNullableWrapper), (intptr_t) (0) } },
     { "methodWithOptionalNullableWrapperIsNull", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionMethodWithOptionalNullableWrapperIsNull), (intptr_t) (0) } },
     { "methodWithOptionalXPathNSResolver", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionMethodWithOptionalXPathNSResolver), (intptr_t) (0) } },
+    { "methodWithOptionalRecord", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionMethodWithOptionalRecord), (intptr_t) (0) } },
     { "methodWithCallbackArg", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionMethodWithCallbackArg), (intptr_t) (1) } },
     { "methodWithNonCallbackArgAndCallbackArg", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionMethodWithNonCallbackArgAndCallbackArg), (intptr_t) (2) } },
     { "methodWithCallbackAndOptionalArg", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionMethodWithCallbackAndOptionalArg), (intptr_t) (0) } },
@@ -2217,6 +2249,102 @@
     return result;
 }
 
+static inline JSValue jsTestObjByteStringAttrTreatingNullAsEmptyStringGetter(ExecState&, JSTestObj&, ThrowScope& throwScope);
+
+EncodedJSValue jsTestObjByteStringAttrTreatingNullAsEmptyString(ExecState* state, EncodedJSValue thisValue, PropertyName)
+{
+    return BindingCaller<JSTestObj>::attribute<jsTestObjByteStringAttrTreatingNullAsEmptyStringGetter>(state, thisValue, "byteStringAttrTreatingNullAsEmptyString");
+}
+
+static inline JSValue jsTestObjByteStringAttrTreatingNullAsEmptyStringGetter(ExecState& state, JSTestObj& thisObject, ThrowScope& throwScope)
+{
+    UNUSED_PARAM(throwScope);
+    UNUSED_PARAM(state);
+    auto& impl = thisObject.wrapped();
+    JSValue result = toJS<IDLByteString>(state, impl.byteStringAttrTreatingNullAsEmptyString());
+    return result;
+}
+
+static inline JSValue jsTestObjStringLongRecordAttrGetter(ExecState&, JSTestObj&, ThrowScope& throwScope);
+
+EncodedJSValue jsTestObjStringLongRecordAttr(ExecState* state, EncodedJSValue thisValue, PropertyName)
+{
+    return BindingCaller<JSTestObj>::attribute<jsTestObjStringLongRecordAttrGetter>(state, thisValue, "stringLongRecordAttr");
+}
+
+static inline JSValue jsTestObjStringLongRecordAttrGetter(ExecState& state, JSTestObj& thisObject, ThrowScope& throwScope)
+{
+    UNUSED_PARAM(throwScope);
+    UNUSED_PARAM(state);
+    auto& impl = thisObject.wrapped();
+    JSValue result = toJS<IDLRecord<IDLDOMString, IDLLong>>(state, *thisObject.globalObject(), impl.stringLongRecordAttr());
+    return result;
+}
+
+static inline JSValue jsTestObjUsvstringLongRecordAttrGetter(ExecState&, JSTestObj&, ThrowScope& throwScope);
+
+EncodedJSValue jsTestObjUsvstringLongRecordAttr(ExecState* state, EncodedJSValue thisValue, PropertyName)
+{
+    return BindingCaller<JSTestObj>::attribute<jsTestObjUsvstringLongRecordAttrGetter>(state, thisValue, "usvstringLongRecordAttr");
+}
+
+static inline JSValue jsTestObjUsvstringLongRecordAttrGetter(ExecState& state, JSTestObj& thisObject, ThrowScope& throwScope)
+{
+    UNUSED_PARAM(throwScope);
+    UNUSED_PARAM(state);
+    auto& impl = thisObject.wrapped();
+    JSValue result = toJS<IDLRecord<IDLUSVString, IDLLong>>(state, *thisObject.globalObject(), impl.usvstringLongRecordAttr());
+    return result;
+}
+
+static inline JSValue jsTestObjUsvstringLongRecordAttrGetter(ExecState&, JSTestObj&, ThrowScope& throwScope);
+
+EncodedJSValue jsTestObjUsvstringLongRecordAttr(ExecState* state, EncodedJSValue thisValue, PropertyName)
+{
+    return BindingCaller<JSTestObj>::attribute<jsTestObjUsvstringLongRecordAttrGetter>(state, thisValue, "usvstringLongRecordAttr");
+}
+
+static inline JSValue jsTestObjUsvstringLongRecordAttrGetter(ExecState& state, JSTestObj& thisObject, ThrowScope& throwScope)
+{
+    UNUSED_PARAM(throwScope);
+    UNUSED_PARAM(state);
+    auto& impl = thisObject.wrapped();
+    JSValue result = toJS<IDLRecord<IDLByteString, IDLLong>>(state, *thisObject.globalObject(), impl.usvstringLongRecordAttr());
+    return result;
+}
+
+static inline JSValue jsTestObjStringObjRecordAttrGetter(ExecState&, JSTestObj&, ThrowScope& throwScope);
+
+EncodedJSValue jsTestObjStringObjRecordAttr(ExecState* state, EncodedJSValue thisValue, PropertyName)
+{
+    return BindingCaller<JSTestObj>::attribute<jsTestObjStringObjRecordAttrGetter>(state, thisValue, "stringObjRecordAttr");
+}
+
+static inline JSValue jsTestObjStringObjRecordAttrGetter(ExecState& state, JSTestObj& thisObject, ThrowScope& throwScope)
+{
+    UNUSED_PARAM(throwScope);
+    UNUSED_PARAM(state);
+    auto& impl = thisObject.wrapped();
+    JSValue result = toJS<IDLRecord<IDLDOMString, IDLInterface<TestObj>>>(state, *thisObject.globalObject(), impl.stringObjRecordAttr());
+    return result;
+}
+
+static inline JSValue jsTestObjStringNullableObjRecordAttrGetter(ExecState&, JSTestObj&, ThrowScope& throwScope);
+
+EncodedJSValue jsTestObjStringNullableObjRecordAttr(ExecState* state, EncodedJSValue thisValue, PropertyName)
+{
+    return BindingCaller<JSTestObj>::attribute<jsTestObjStringNullableObjRecordAttrGetter>(state, thisValue, "stringNullableObjRecordAttr");
+}
+
+static inline JSValue jsTestObjStringNullableObjRecordAttrGetter(ExecState& state, JSTestObj& thisObject, ThrowScope& throwScope)
+{
+    UNUSED_PARAM(throwScope);
+    UNUSED_PARAM(state);
+    auto& impl = thisObject.wrapped();
+    JSValue result = toJS<IDLRecord<IDLDOMString, IDLNullable<IDLInterface<TestObj>>>>(state, *thisObject.globalObject(), impl.stringNullableObjRecordAttr());
+    return result;
+}
+
 static inline JSValue jsTestObjImplementationEnumAttrGetter(ExecState&, JSTestObj&, ThrowScope& throwScope);
 
 EncodedJSValue jsTestObjImplementationEnumAttr(ExecState* state, EncodedJSValue thisValue, PropertyName)
@@ -3143,6 +3271,22 @@
     return result;
 }
 
+static inline JSValue jsTestObjNullableByteStringSettableAttributeGetter(ExecState&, JSTestObj&, ThrowScope& throwScope);
+
+EncodedJSValue jsTestObjNullableByteStringSettableAttribute(ExecState* state, EncodedJSValue thisValue, PropertyName)
+{
+    return BindingCaller<JSTestObj>::attribute<jsTestObjNullableByteStringSettableAttributeGetter>(state, thisValue, "nullableByteStringSettableAttribute");
+}
+
+static inline JSValue jsTestObjNullableByteStringSettableAttributeGetter(ExecState& state, JSTestObj& thisObject, ThrowScope& throwScope)
+{
+    UNUSED_PARAM(throwScope);
+    UNUSED_PARAM(state);
+    auto& impl = thisObject.wrapped();
+    JSValue result = toJS<IDLNullable<IDLByteString>>(state, impl.nullableByteStringSettableAttribute());
+    return result;
+}
+
 static inline JSValue jsTestObjNullableStringValueGetter(ExecState&, JSTestObj&, ThrowScope& throwScope);
 
 EncodedJSValue jsTestObjNullableStringValue(ExecState* state, EncodedJSValue thisValue, PropertyName)
@@ -3633,6 +3777,120 @@
 }
 
 
+static inline bool setJSTestObjByteStringAttrTreatingNullAsEmptyStringFunction(ExecState&, JSTestObj&, JSValue, ThrowScope&);
+
+bool setJSTestObjByteStringAttrTreatingNullAsEmptyString(ExecState* state, EncodedJSValue thisValue, EncodedJSValue encodedValue)
+{
+    return BindingCaller<JSTestObj>::setAttribute<setJSTestObjByteStringAttrTreatingNullAsEmptyStringFunction>(state, thisValue, encodedValue, "byteStringAttrTreatingNullAsEmptyString");
+}
+
+static inline bool setJSTestObjByteStringAttrTreatingNullAsEmptyStringFunction(ExecState& state, JSTestObj& thisObject, JSValue value, ThrowScope& throwScope)
+{
+    UNUSED_PARAM(state);
+    UNUSED_PARAM(throwScope);
+    auto& impl = thisObject.wrapped();
+    auto nativeValue = convert<IDLByteString>(state, value, StringConversionConfiguration::TreatNullAsEmptyString);
+    RETURN_IF_EXCEPTION(throwScope, false);
+    impl.setByteStringAttrTreatingNullAsEmptyString(WTFMove(nativeValue));
+    return true;
+}
+
+
+static inline bool setJSTestObjStringLongRecordAttrFunction(ExecState&, JSTestObj&, JSValue, ThrowScope&);
+
+bool setJSTestObjStringLongRecordAttr(ExecState* state, EncodedJSValue thisValue, EncodedJSValue encodedValue)
+{
+    return BindingCaller<JSTestObj>::setAttribute<setJSTestObjStringLongRecordAttrFunction>(state, thisValue, encodedValue, "stringLongRecordAttr");
+}
+
+static inline bool setJSTestObjStringLongRecordAttrFunction(ExecState& state, JSTestObj& thisObject, JSValue value, ThrowScope& throwScope)
+{
+    UNUSED_PARAM(state);
+    UNUSED_PARAM(throwScope);
+    auto& impl = thisObject.wrapped();
+    auto nativeValue = convert<IDLRecord<IDLDOMString, IDLLong>>(state, value);
+    RETURN_IF_EXCEPTION(throwScope, false);
+    impl.setStringLongRecordAttr(WTFMove(nativeValue));
+    return true;
+}
+
+
+static inline bool setJSTestObjUsvstringLongRecordAttrFunction(ExecState&, JSTestObj&, JSValue, ThrowScope&);
+
+bool setJSTestObjUsvstringLongRecordAttr(ExecState* state, EncodedJSValue thisValue, EncodedJSValue encodedValue)
+{
+    return BindingCaller<JSTestObj>::setAttribute<setJSTestObjUsvstringLongRecordAttrFunction>(state, thisValue, encodedValue, "usvstringLongRecordAttr");
+}
+
+static inline bool setJSTestObjUsvstringLongRecordAttrFunction(ExecState& state, JSTestObj& thisObject, JSValue value, ThrowScope& throwScope)
+{
+    UNUSED_PARAM(state);
+    UNUSED_PARAM(throwScope);
+    auto& impl = thisObject.wrapped();
+    auto nativeValue = convert<IDLRecord<IDLUSVString, IDLLong>>(state, value);
+    RETURN_IF_EXCEPTION(throwScope, false);
+    impl.setUsvstringLongRecordAttr(WTFMove(nativeValue));
+    return true;
+}
+
+
+static inline bool setJSTestObjUsvstringLongRecordAttrFunction(ExecState&, JSTestObj&, JSValue, ThrowScope&);
+
+bool setJSTestObjUsvstringLongRecordAttr(ExecState* state, EncodedJSValue thisValue, EncodedJSValue encodedValue)
+{
+    return BindingCaller<JSTestObj>::setAttribute<setJSTestObjUsvstringLongRecordAttrFunction>(state, thisValue, encodedValue, "usvstringLongRecordAttr");
+}
+
+static inline bool setJSTestObjUsvstringLongRecordAttrFunction(ExecState& state, JSTestObj& thisObject, JSValue value, ThrowScope& throwScope)
+{
+    UNUSED_PARAM(state);
+    UNUSED_PARAM(throwScope);
+    auto& impl = thisObject.wrapped();
+    auto nativeValue = convert<IDLRecord<IDLByteString, IDLLong>>(state, value);
+    RETURN_IF_EXCEPTION(throwScope, false);
+    impl.setUsvstringLongRecordAttr(WTFMove(nativeValue));
+    return true;
+}
+
+
+static inline bool setJSTestObjStringObjRecordAttrFunction(ExecState&, JSTestObj&, JSValue, ThrowScope&);
+
+bool setJSTestObjStringObjRecordAttr(ExecState* state, EncodedJSValue thisValue, EncodedJSValue encodedValue)
+{
+    return BindingCaller<JSTestObj>::setAttribute<setJSTestObjStringObjRecordAttrFunction>(state, thisValue, encodedValue, "stringObjRecordAttr");
+}
+
+static inline bool setJSTestObjStringObjRecordAttrFunction(ExecState& state, JSTestObj& thisObject, JSValue value, ThrowScope& throwScope)
+{
+    UNUSED_PARAM(state);
+    UNUSED_PARAM(throwScope);
+    auto& impl = thisObject.wrapped();
+    auto nativeValue = convert<IDLRecord<IDLDOMString, IDLInterface<TestObj>>>(state, value);
+    RETURN_IF_EXCEPTION(throwScope, false);
+    impl.setStringObjRecordAttr(WTFMove(nativeValue));
+    return true;
+}
+
+
+static inline bool setJSTestObjStringNullableObjRecordAttrFunction(ExecState&, JSTestObj&, JSValue, ThrowScope&);
+
+bool setJSTestObjStringNullableObjRecordAttr(ExecState* state, EncodedJSValue thisValue, EncodedJSValue encodedValue)
+{
+    return BindingCaller<JSTestObj>::setAttribute<setJSTestObjStringNullableObjRecordAttrFunction>(state, thisValue, encodedValue, "stringNullableObjRecordAttr");
+}
+
+static inline bool setJSTestObjStringNullableObjRecordAttrFunction(ExecState& state, JSTestObj& thisObject, JSValue value, ThrowScope& throwScope)
+{
+    UNUSED_PARAM(state);
+    UNUSED_PARAM(throwScope);
+    auto& impl = thisObject.wrapped();
+    auto nativeValue = convert<IDLRecord<IDLDOMString, IDLNullable<IDLInterface<TestObj>>>>(state, value);
+    RETURN_IF_EXCEPTION(throwScope, false);
+    impl.setStringNullableObjRecordAttr(WTFMove(nativeValue));
+    return true;
+}
+
+
 static inline bool setJSTestObjImplementationEnumAttrFunction(ExecState&, JSTestObj&, JSValue, ThrowScope&);
 
 bool setJSTestObjImplementationEnumAttr(ExecState* state, EncodedJSValue thisValue, EncodedJSValue encodedValue)
@@ -4536,6 +4794,25 @@
 }
 
 
+static inline bool setJSTestObjNullableByteStringSettableAttributeFunction(ExecState&, JSTestObj&, JSValue, ThrowScope&);
+
+bool setJSTestObjNullableByteStringSettableAttribute(ExecState* state, EncodedJSValue thisValue, EncodedJSValue encodedValue)
+{
+    return BindingCaller<JSTestObj>::setAttribute<setJSTestObjNullableByteStringSettableAttributeFunction>(state, thisValue, encodedValue, "nullableByteStringSettableAttribute");
+}
+
+static inline bool setJSTestObjNullableByteStringSettableAttributeFunction(ExecState& state, JSTestObj& thisObject, JSValue value, ThrowScope& throwScope)
+{
+    UNUSED_PARAM(state);
+    UNUSED_PARAM(throwScope);
+    auto& impl = thisObject.wrapped();
+    auto nativeValue = convert<IDLNullable<IDLByteString>>(state, value, StringConversionConfiguration::Normal);
+    RETURN_IF_EXCEPTION(throwScope, false);
+    impl.setNullableByteStringSettableAttribute(WTFMove(nativeValue));
+    return true;
+}
+
+
 static inline bool setJSTestObjNullableStringValueFunction(ExecState&, JSTestObj&, JSValue, ThrowScope&);
 
 bool setJSTestObjNullableStringValue(ExecState* state, EncodedJSValue thisValue, EncodedJSValue encodedValue)
@@ -5211,6 +5488,66 @@
     return JSValue::encode(jsUndefined());
 }
 
+static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionMethodWithByteStringArgCaller(JSC::ExecState*, JSTestObj*, JSC::ThrowScope&);
+
+EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionMethodWithByteStringArg(ExecState* state)
+{
+    return BindingCaller<JSTestObj>::callOperation<jsTestObjPrototypeFunctionMethodWithByteStringArgCaller>(state, "methodWithByteStringArg");
+}
+
+static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionMethodWithByteStringArgCaller(JSC::ExecState* state, JSTestObj* castedThis, JSC::ThrowScope& throwScope)
+{
+    UNUSED_PARAM(state);
+    UNUSED_PARAM(throwScope);
+    auto& impl = castedThis->wrapped();
+    if (UNLIKELY(state->argumentCount() < 1))
+        return throwVMError(state, throwScope, createNotEnoughArgumentsError(state));
+    auto str = convert<IDLByteString>(*state, state->uncheckedArgument(0), StringConversionConfiguration::Normal);
+    RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
+    impl.methodWithByteStringArg(WTFMove(str));
+    return JSValue::encode(jsUndefined());
+}
+
+static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionMethodWithNullableByteStringArgCaller(JSC::ExecState*, JSTestObj*, JSC::ThrowScope&);
+
+EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionMethodWithNullableByteStringArg(ExecState* state)
+{
+    return BindingCaller<JSTestObj>::callOperation<jsTestObjPrototypeFunctionMethodWithNullableByteStringArgCaller>(state, "methodWithNullableByteStringArg");
+}
+
+static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionMethodWithNullableByteStringArgCaller(JSC::ExecState* state, JSTestObj* castedThis, JSC::ThrowScope& throwScope)
+{
+    UNUSED_PARAM(state);
+    UNUSED_PARAM(throwScope);
+    auto& impl = castedThis->wrapped();
+    if (UNLIKELY(state->argumentCount() < 1))
+        return throwVMError(state, throwScope, createNotEnoughArgumentsError(state));
+    auto str = convert<IDLNullable<IDLByteString>>(*state, state->uncheckedArgument(0), StringConversionConfiguration::Normal);
+    RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
+    impl.methodWithNullableByteStringArg(WTFMove(str));
+    return JSValue::encode(jsUndefined());
+}
+
+static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionMethodWithByteStringArgTreatingNullAsEmptyStringCaller(JSC::ExecState*, JSTestObj*, JSC::ThrowScope&);
+
+EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionMethodWithByteStringArgTreatingNullAsEmptyString(ExecState* state)
+{
+    return BindingCaller<JSTestObj>::callOperation<jsTestObjPrototypeFunctionMethodWithByteStringArgTreatingNullAsEmptyStringCaller>(state, "methodWithByteStringArgTreatingNullAsEmptyString");
+}
+
+static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionMethodWithByteStringArgTreatingNullAsEmptyStringCaller(JSC::ExecState* state, JSTestObj* castedThis, JSC::ThrowScope& throwScope)
+{
+    UNUSED_PARAM(state);
+    UNUSED_PARAM(throwScope);
+    auto& impl = castedThis->wrapped();
+    if (UNLIKELY(state->argumentCount() < 1))
+        return throwVMError(state, throwScope, createNotEnoughArgumentsError(state));
+    auto str = convert<IDLByteString>(*state, state->uncheckedArgument(0), StringConversionConfiguration::TreatNullAsEmptyString);
+    RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
+    impl.methodWithByteStringArgTreatingNullAsEmptyString(WTFMove(str));
+    return JSValue::encode(jsUndefined());
+}
+
 static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionSerializedValueCaller(JSC::ExecState*, JSTestObj*, JSC::ThrowScope&);
 
 EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionSerializedValue(ExecState* state)
@@ -5251,6 +5588,26 @@
     return JSValue::encode(jsUndefined());
 }
 
+static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionMethodWithRecordCaller(JSC::ExecState*, JSTestObj*, JSC::ThrowScope&);
+
+EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionMethodWithRecord(ExecState* state)
+{
+    return BindingCaller<JSTestObj>::callOperation<jsTestObjPrototypeFunctionMethodWithRecordCaller>(state, "methodWithRecord");
+}
+
+static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionMethodWithRecordCaller(JSC::ExecState* state, JSTestObj* castedThis, JSC::ThrowScope& throwScope)
+{
+    UNUSED_PARAM(state);
+    UNUSED_PARAM(throwScope);
+    auto& impl = castedThis->wrapped();
+    if (UNLIKELY(state->argumentCount() < 1))
+        return throwVMError(state, throwScope, createNotEnoughArgumentsError(state));
+    auto recordParameter = convert<IDLRecord<IDLDOMString, IDLLong>>(*state, state->uncheckedArgument(0));
+    RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
+    impl.methodWithRecord(WTFMove(recordParameter));
+    return JSValue::encode(jsUndefined());
+}
+
 static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionMethodWithExceptionCaller(JSC::ExecState*, JSTestObj*, JSC::ThrowScope&);
 
 EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionMethodWithException(ExecState* state)
@@ -6159,6 +6516,24 @@
     return JSValue::encode(jsUndefined());
 }
 
+static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionMethodWithOptionalRecordCaller(JSC::ExecState*, JSTestObj*, JSC::ThrowScope&);
+
+EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionMethodWithOptionalRecord(ExecState* state)
+{
+    return BindingCaller<JSTestObj>::callOperation<jsTestObjPrototypeFunctionMethodWithOptionalRecordCaller>(state, "methodWithOptionalRecord");
+}
+
+static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionMethodWithOptionalRecordCaller(JSC::ExecState* state, JSTestObj* castedThis, JSC::ThrowScope& throwScope)
+{
+    UNUSED_PARAM(state);
+    UNUSED_PARAM(throwScope);
+    auto& impl = castedThis->wrapped();
+    auto record = state->argument(0).isUndefined() ? Nullopt : convert<IDLNullable<IDLRecord<IDLDOMString, IDLLong>>>(*state, state->uncheckedArgument(0));
+    RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
+    impl.methodWithOptionalRecord(WTFMove(record));
+    return JSValue::encode(jsUndefined());
+}
+
 static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionMethodWithCallbackArgCaller(JSC::ExecState*, JSTestObj*, JSC::ThrowScope&);
 
 EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionMethodWithCallbackArg(ExecState* state)

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


--- trunk/Source/WebCore/bindings/scripts/test/TestObj.idl	2016-11-18 21:41:40 UTC (rev 208892)
+++ trunk/Source/WebCore/bindings/scripts/test/TestObj.idl	2016-11-18 21:47:42 UTC (rev 208893)
@@ -58,28 +58,30 @@
     static attribute DOMString         staticStringAttr;
     static readonly attribute TestSubObjConstructor TestSubObj;
     [EnabledBySetting=TestSetting] attribute TestSubObjConstructor TestSubObjEnabledBySetting;
-    attribute TestEnumType             enumAttr;
-    attribute byte                     byteAttr;
-    attribute octet                    octetAttr;
-    [Unscopable] attribute short                    shortAttr;
-    [Clamp] attribute short            clampedShortAttr;
-    [EnforceRange] attribute short     enforceRangeShortAttr;
-    attribute unsigned short           unsignedShortAttr;
-    attribute long                     longAttr;
-    attribute long long                longLongAttr;
-    attribute unsigned long long       unsignedLongLongAttr;
-    attribute DOMString                stringAttr;
-#if defined(TESTING_JS)
-    attribute USVString                usvstringAttr;
-#endif
-    attribute TestObj                  testObjAttr;
-    attribute TestObj?                 testNullableObjAttr;
-    [LenientThis] attribute TestObj    lenientTestObjAttr;
+    attribute TestEnumType enumAttr;
+    attribute byte byteAttr;
+    attribute octet octetAttr;
+    [Unscopable] attribute short shortAttr;
+    [Clamp] attribute short clampedShortAttr;
+    [EnforceRange] attribute short enforceRangeShortAttr;
+    attribute unsigned short unsignedShortAttr;
+    attribute long longAttr;
+    attribute long long longLongAttr;
+    attribute unsigned long long unsignedLongLongAttr;
+    attribute DOMString stringAttr;
+    attribute USVString usvstringAttr;
+    attribute TestObj testObjAttr;
+    attribute TestObj? testNullableObjAttr;
+    [LenientThis] attribute TestObj lenientTestObjAttr;
     [Unforgeable] readonly attribute DOMString unforgeableAttr;
     [TreatNullAs=EmptyString] attribute DOMString stringAttrTreatingNullAsEmptyString;
-#if defined(TESTING_JS)
     [TreatNullAs=EmptyString] attribute USVString usvstringAttrTreatingNullAsEmptyString;
-#endif
+    [TreatNullAs=EmptyString] attribute ByteString byteStringAttrTreatingNullAsEmptyString;
+    attribute record<DOMString, long> stringLongRecordAttr;
+    attribute record<USVString, long> usvstringLongRecordAttr;
+    attribute record<ByteString, long> usvstringLongRecordAttr;
+    attribute record<DOMString, TestObj> stringObjRecordAttr;
+    attribute record<DOMString, TestObj?> stringNullableObjRecordAttr;
 
     attribute TestEnumTypeWithAlternateImplementationName implementationEnumAttr;
 
@@ -89,16 +91,12 @@
 
     // Reflected DOM attributes
     [Reflect] attribute DOMString reflectedStringAttr;
-#if defined(TESTING_JS)
     [Reflect] attribute USVString reflectedUSVStringAttr;
-#endif
     [Reflect] attribute long reflectedIntegralAttr;
     [Reflect] attribute unsigned long reflectedUnsignedIntegralAttr;
     [Reflect] attribute boolean reflectedBooleanAttr;
     [Reflect, URL] attribute DOMString reflectedURLAttr;
-#if defined(TESTING_JS)
     [Reflect, URL] attribute USVString reflectedUSVURLAttr;
-#endif
     [Reflect=customContentStringAttr] attribute DOMString reflectedStringAttr;
     [Reflect=customContentIntegralAttr] attribute long reflectedCustomIntegralAttr;
     [Reflect=customContentBooleanAttr] attribute boolean reflectedCustomBooleanAttr;
@@ -142,15 +140,19 @@
     void methodWithOptionalEnumArgAndDefaultValue(optional TestEnumType enumArg = "EnumValue1");
     [MayThrowException] TestObj methodThatRequiresAllArgsAndThrows(DOMString strArg, TestObj objArg);
 
-#if defined(TESTING_JS)
     void methodWithUSVStringArg(USVString str);
     void methodWithNullableUSVStringArg(USVString? str);
     void methodWithUSVStringArgTreatingNullAsEmptyString([TreatNullAs=EmptyString] USVString str);
-#endif
 
+    void methodWithByteStringArg(ByteString str);
+    void methodWithNullableByteStringArg(ByteString? str);
+    void methodWithByteStringArgTreatingNullAsEmptyString([TreatNullAs=EmptyString] ByteString str);
+
     void serializedValue(SerializedScriptValue serializedArg);
     void optionsObject(Dictionary oo, optional Dictionary ooo);
 
+    void methodWithRecord(record<DOMString, long> recordParameter);
+
     // Exceptions
     [MayThrowException] void methodWithException();
     [MayThrowException] long methodWithExceptionReturningLong();
@@ -210,9 +212,7 @@
     void    methodWithNonOptionalArgAndOptionalArg(long nonOpt, optional long opt);
     void    methodWithNonOptionalArgAndTwoOptionalArgs(long nonOpt, optional long opt1, optional long opt2);
     void    methodWithOptionalString(optional DOMString str);
-#if defined(TESTING_JS)
     void    methodWithOptionalUSVString(optional USVString str);
-#endif
     void    methodWithOptionalAtomicString([AtomicString] optional DOMString str);
     void    methodWithOptionalStringAndDefaultValue(optional DOMString str = "foo");
     void    methodWithOptionalAtomicStringAndDefaultValue([AtomicString] optional DOMString str = "foo");
@@ -220,9 +220,7 @@
     void    methodWithOptionalStringIsUndefined(optional DOMString str = "undefined");
     void    methodWithOptionalAtomicStringIsNull([AtomicString] optional DOMString str = null);
     void    methodWithOptionalStringIsEmptyString(optional DOMString str = "");
-#if defined(TESTING_JS)
     void    methodWithOptionalUSVStringIsEmptyString(optional USVString str = "");
-#endif
     void    methodWithOptionalAtomicStringIsEmptyString([AtomicString] optional DOMString str = "");
     void    methodWithOptionalDoubleIsNaN(optional unrestricted double number = NaN);
     void    methodWithOptionalFloatIsNaN(optional unrestricted float number = NaN);
@@ -238,8 +236,8 @@
     void    methodWithOptionalNullableWrapper(optional TestObj? obj);
     void    methodWithOptionalNullableWrapperIsNull(optional TestObj? obj = null);
     void    methodWithOptionalXPathNSResolver(optional XPathNSResolver? resolver);
+    void    methodWithOptionalRecord(optional record<DOMString, long>? record = null);
 
-#if defined(TESTING_JS)
     // Callback interface parameters.
     void    methodWithCallbackArg(TestCallbackInterface callback);
     void    methodWithNonCallbackArgAndCallbackArg(long nonCallback, TestCallbackInterface callback);
@@ -253,7 +251,6 @@
     // static methods with 'Callback' extended attribute
     static void    staticMethodWithCallbackAndOptionalArg(optional TestCallbackInterface? callback);
     static void    staticMethodWithCallbackArg(TestCallbackInterface callback);
-#endif
 
     // 'Conditional' extended attribute
     [Conditional=Condition1] attribute long conditionalAttr1;
@@ -271,14 +268,11 @@
 
     [Conditional=Condition1] const unsigned short CONDITIONAL_CONST = 0;
 
-#if defined(TESTING_JS)
     [CachedAttribute] readonly attribute any cachedAttribute1;
     [CachedAttribute] readonly attribute any cachedAttribute2;
-#endif
     
     attribute any anyAttribute;
 
-#if defined(TESTING_JS)
     // Overloads
     void    overloadedMethod(TestObj? objArg, DOMString strArg);
     void    overloadedMethod(TestObj? objArg, optional long longArg);
@@ -316,7 +310,6 @@
 
     void overloadWithNullableNonDistinguishingParameter(TestObj? obj, TestNode node);
     void overloadWithNullableNonDistinguishingParameter(TestNode? node, long index);
-#endif
 
     // Class methods within _javascript_ (like what's used for IDBKeyRange).
     static void classMethod();
@@ -330,7 +323,6 @@
     void classMethodWithClamp([Clamp] unsigned short objArgsShort, [Clamp] unsigned long objArgsLong);
     void classMethodWithEnforceRange([EnforceRange] unsigned short objArgsShort, [EnforceRange] unsigned long objArgsLong);
 
-#if defined(TESTING_JS)
     void methodWithUnsignedLongSequence(sequence<unsigned long> unsignedLongSequence);
     [MayThrowException] sequence<DOMString> stringArrayFunction(sequence<DOMString> values);
     [MayThrowException] DOMStringList domStringListFunction(DOMStringList values);
@@ -338,7 +330,6 @@
     void methodWithAndWithoutNullableSequence(sequence<unsigned long> arrayArg, sequence<unsigned long>? nullableArrayArg);
 
     Element? getElementById([RequiresExistingAtomicString] DOMString elementId);
-#endif
 
     [CheckSecurityForNode] readonly attribute Document contentDocument;
     [CheckSecurityForNode, MayThrowException] SVGDocument getSVGDocument();
@@ -389,9 +380,8 @@
 
     attribute long? nullableLongSettableAttribute;
     attribute DOMString? nullableStringSettableAttribute;
-#if defined(TESTING_JS)
     attribute USVString? nullableUSVStringSettableAttribute;
-#endif
+    attribute ByteString? nullableByteStringSettableAttribute;
 
     [GetterMayThrowException] attribute long? nullableStringValue;
 
@@ -418,7 +408,6 @@
     [PutForwards=name] readonly attribute TestNode putForwardsAttribute;
     [PutForwards=name] readonly attribute TestNode? putForwardsNullableAttribute;
 
-#if defined(TESTING_JS)
     // Overloading with conditionals.
     [Conditional=CONDITION1] void conditionalOverload(DOMString str);
     [Conditional=CONDITION2] void conditionalOverload(long a);
@@ -425,7 +414,6 @@
 
     void singleConditionalOverload(DOMString str);
     [Conditional=CONDITION] void singleConditionalOverload(long a);
-#endif
 
     void attachShadowRoot(TestDictionary init);
     void operationWithExternalDictionaryParameter(TestStandaloneDictionary dict);

Modified: trunk/Source/WebCore/testing/TypeConversions.h (208892 => 208893)


--- trunk/Source/WebCore/testing/TypeConversions.h	2016-11-18 21:41:40 UTC (rev 208892)
+++ trunk/Source/WebCore/testing/TypeConversions.h	2016-11-18 21:47:42 UTC (rev 208893)
@@ -27,6 +27,7 @@
 
 #include "Node.h"
 #include <wtf/FastMalloc.h>
+#include <wtf/HashMap.h>
 #include <wtf/RefCounted.h>
 #include <wtf/Variant.h>
 #include <wtf/Vector.h>
@@ -101,6 +102,13 @@
     const String& testByteString() const { return m_byteString; }
     void setTestByteString(const String& byteString) { m_byteString = byteString; }
 
+    const HashMap<String, int>& testLongRecord() const { return m_longRecord; }
+    void setTestLongRecord(const HashMap<String, int>& value) { m_longRecord = value; }
+    const HashMap<String, RefPtr<Node>>& testNodeRecord() const { return m_nodeRecord; }
+    void setTestNodeRecord(const HashMap<String, RefPtr<Node>>& value) { m_nodeRecord = value; }
+    const HashMap<String, Vector<String>>& testSequenceRecord() const { return m_sequenceRecord; }
+    void setTestSequenceRecord(const HashMap<String, Vector<String>>& value) { m_sequenceRecord = value; }
+
     using TestUnion = Variant<String, int, bool, RefPtr<Node>, Vector<int>>;
     const TestUnion& testUnion() const { return m_union; }
     void setTestUnion(const TestUnion& value) { m_union = value; }
@@ -142,6 +150,9 @@
     String m_string;
     String m_usvstring;
     String m_byteString;
+    HashMap<String, int> m_longRecord;
+    HashMap<String, RefPtr<Node>> m_nodeRecord;
+    HashMap<String, Vector<String>> m_sequenceRecord;
     TestUnion m_union;
     
     int m_typeConversionsDictionaryLongValue { 0 };

Modified: trunk/Source/WebCore/testing/TypeConversions.idl (208892 => 208893)


--- trunk/Source/WebCore/testing/TypeConversions.idl	2016-11-18 21:41:40 UTC (rev 208892)
+++ trunk/Source/WebCore/testing/TypeConversions.idl	2016-11-18 21:47:42 UTC (rev 208893)
@@ -54,6 +54,10 @@
     attribute ByteString testByteString;
     attribute USVString testUSVString;
 
+    attribute record<DOMString, long> testLongRecord;
+    attribute record<USVString, Node> testNodeRecord;
+    attribute record<ByteString, sequence<DOMString>> testSequenceRecord;
+
     attribute (DOMString or long or boolean or Node or sequence<long>) testUnion;
     
     void setTypeConversionsDictionary(TypeConversionsDictionary d);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to