Changeset 207575 in webkit
- Timestamp:
- Oct 19, 2016 4:31:14 PM (7 years ago)
- Location:
- trunk
- Files:
-
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r207574 r207575 1 2016-10-19 Sam Weinig <sam@webkit.org> 2 3 Add support for sequences and dictionaries in unions 4 https://bugs.webkit.org/show_bug.cgi?id=163695 5 6 Reviewed by Chris Dumez. 7 8 * js/dom/webidl-type-mapping-expected.txt: 9 * js/dom/webidl-type-mapping.html: 10 Add tests for more complex conversions. 11 1 12 2016-10-19 Ryan Haddad <ryanhaddad@apple.com> 2 13 -
trunk/LayoutTests/js/dom/webidl-type-mapping-expected.txt
r204215 r207575 1060 1060 PASS converter.testUSVString is "undefined" 1061 1061 PASS converter.testString is "undefined" 1062 converter.setTypeConversionsDictionary({ longValue: 1 }) 1063 PASS converter.typeConversionsDictionaryLongValue is 1 1064 converter.setTypeConversionsDictionary({ stringValue: 'hello' }) 1065 PASS converter.typeConversionsDictionaryStringValue is 'hello' 1066 converter.setTypeConversionsDictionary({ sequenceValue: ['hi', 'there'] }) 1067 PASS converter.typeConversionsDictionarySequenceValue is ['hi', 'there'] 1068 converter.setTypeConversionsDictionary({ unionValue: document }) 1069 PASS converter.typeConversionsDictionaryUnionType is 'node' 1070 converter.setTypeConversionsDictionary({ unionValue: ['a', 'sequence'] }) 1071 PASS converter.typeConversionsDictionaryUnionType is 'sequence' 1072 converter.setTypeConversionsDictionary({ unionValue: { longValue: 1 } }) 1073 PASS converter.typeConversionsDictionaryUnionType is 'dictionary' 1074 converter.setTypeConversionsDictionary({ unionValue: null }) 1075 PASS converter.typeConversionsDictionaryUnionType is 'dictionary' 1076 converter.setTypeConversionsDictionary({ unionValue: undefined }) 1077 PASS converter.typeConversionsDictionaryUnionType is 'dictionary' 1078 converter.setTypeConversionsDictionary({ }) 1079 PASS converter.typeConversionsDictionaryUnionType is 'dictionary' 1062 1080 PASS successfullyParsed is true 1063 1081 -
trunk/LayoutTests/js/dom/webidl-type-mapping.html
r204215 r207575 587 587 }); 588 588 589 evalAndLog("converter.setTypeConversionsDictionary({ longValue: 1 })"); 590 shouldBe("converter.typeConversionsDictionaryLongValue", "1"); 591 evalAndLog("converter.setTypeConversionsDictionary({ stringValue: 'hello' })"); 592 shouldBe("converter.typeConversionsDictionaryStringValue", "'hello'"); 593 evalAndLog("converter.setTypeConversionsDictionary({ sequenceValue: ['hi', 'there'] })"); 594 shouldBe("converter.typeConversionsDictionarySequenceValue", "['hi', 'there']"); 595 596 evalAndLog("converter.setTypeConversionsDictionary({ unionValue: document })"); 597 shouldBe("converter.typeConversionsDictionaryUnionType", "'node'"); 598 evalAndLog("converter.setTypeConversionsDictionary({ unionValue: ['a', 'sequence'] })"); 599 shouldBe("converter.typeConversionsDictionaryUnionType", "'sequence'"); 600 evalAndLog("converter.setTypeConversionsDictionary({ unionValue: { longValue: 1 } })"); 601 shouldBe("converter.typeConversionsDictionaryUnionType", "'dictionary'"); 602 evalAndLog("converter.setTypeConversionsDictionary({ unionValue: null })"); 603 shouldBe("converter.typeConversionsDictionaryUnionType", "'dictionary'"); 604 evalAndLog("converter.setTypeConversionsDictionary({ unionValue: undefined })"); 605 shouldBe("converter.typeConversionsDictionaryUnionType", "'dictionary'"); 606 evalAndLog("converter.setTypeConversionsDictionary({ })"); 607 shouldBe("converter.typeConversionsDictionaryUnionType", "'dictionary'"); 608 589 609 </script> 590 610 <script src="../../resources/js-test-post.js"></script> -
trunk/Source/WebCore/ChangeLog
r207571 r207575 1 2016-10-19 Sam Weinig <sam@webkit.org> 2 3 Add support for sequences and dictionaries in unions 4 https://bugs.webkit.org/show_bug.cgi?id=163695 5 6 Reviewed by Chris Dumez. 7 8 Tests: 9 - Updated js/dom/webidl-type-mapping.html 10 11 * bindings/generic/IDLTypes.h: 12 Add additional helper predicates and fix formatting. 13 14 * bindings/js/JSDOMBinding.h: 15 Export hasIteratorMethod for use in testing. 16 17 * bindings/js/JSDOMConvert.h: 18 - Change return type of Converter<IDLDictionary<T>> to T, from Optional<T>. 19 - Add support for unions conversion step 12 (parts 1-3). 20 21 * bindings/scripts/CodeGeneratorJS.pm: 22 (GenerateDefaultValue): 23 Support complex default value computations for unions using the convert infrastructure. 24 25 (GenerateParametersCheck): 26 (GenerateConstructorDefinition): 27 Remove incorrect .value() calls now that Converter<IDLDictionary<T>> returns T. 28 29 * bindings/scripts/test/JS/JSTestEventConstructor.cpp: 30 * bindings/scripts/test/JS/JSTestObj.cpp: 31 Update bindings test results. 32 33 * testing/TypeConversions.h: 34 (WebCore::TypeConversions::setTypeConversionsDictionary): 35 (WebCore::TypeConversions::typeConversionsDictionaryLongValue): 36 (WebCore::TypeConversions::typeConversionsDictionaryStringValue): 37 (WebCore::TypeConversions::typeConversionsDictionarySequenceValue): 38 (WebCore::TypeConversions::typeConversionsDictionaryUnionType): 39 * testing/TypeConversions.idl: 40 Add some complex types to allow testing IDL conversions from tests. 41 1 42 2016-10-19 Ryosuke Niwa <rniwa@webkit.org> 2 43 -
trunk/Source/WebCore/bindings/generic/IDLTypes.h
r207517 r207575 124 124 // Helper predicates 125 125 126 template 126 template<typename T> 127 127 struct IsIDLInterface : public std::integral_constant<bool, WTF::IsTemplate<T, IDLInterface>::value> { }; 128 128 129 template 129 template<typename T> 130 130 struct IsIDLDictionary : public std::integral_constant<bool, WTF::IsTemplate<T, IDLDictionary>::value> { }; 131 131 132 template <typename T> 132 template<typename T> 133 struct IsIDLEnumeration : public std::integral_constant<bool, WTF::IsTemplate<T, IDLEnumeration>::value> { }; 134 135 template<typename T> 136 struct IsIDLSequence : public std::integral_constant<bool, WTF::IsTemplate<T, IDLSequence>::value> { }; 137 138 template<typename T> 139 struct IsIDLFrozenArray : public std::integral_constant<bool, WTF::IsTemplate<T, IDLFrozenArray>::value> { }; 140 141 template<typename T> 133 142 struct IsIDLNumber : public std::integral_constant<bool, WTF::IsBaseOfTemplate<IDLNumber, T>::value> { }; 134 143 135 template 144 template<typename T> 136 145 struct IsIDLInteger : public std::integral_constant<bool, WTF::IsBaseOfTemplate<IDLInteger, T>::value> { }; 137 146 -
trunk/Source/WebCore/bindings/js/JSDOMBinding.h
r207521 r207575 302 302 303 303 template<typename T, typename JSType> Vector<Ref<T>> toRefNativeArray(JSC::ExecState&, JSC::JSValue); 304 bool hasIteratorMethod(JSC::ExecState&, JSC::JSValue);304 WEBCORE_EXPORT bool hasIteratorMethod(JSC::ExecState&, JSC::JSValue); 305 305 306 306 bool shouldAllowAccessToNode(JSC::ExecState*, Node*); -
trunk/Source/WebCore/bindings/js/JSDOMConvert.h
r207498 r207575 409 409 410 410 template<typename T> struct Converter<IDLDictionary<T>> : DefaultConverter<IDLDictionary<T>> { 411 using ReturnType = Optional<T>;411 using ReturnType = T; 412 412 413 413 static ReturnType convert(JSC::ExecState& state, JSC::JSValue value) … … 477 477 using ReturnType = typename Type::ImplementationType; 478 478 479 using DictionaryTypeList = brigand::find<TypeList, IsIDLDictionary<brigand::_1>>; 480 using DictionaryType = ConditionalFront<DictionaryTypeList, brigand::size<DictionaryTypeList>::value != 0>; 481 static_assert(brigand::size<DictionaryTypeList>::value == 0 || brigand::size<DictionaryTypeList>::value == 1, "There can be 0 or 1 dictionary types in an IDLUnion."); 482 483 using NumericTypeList = brigand::find<TypeList, IsIDLNumber<brigand::_1>>; 484 using NumericType = ConditionalFront<NumericTypeList, brigand::size<NumericTypeList>::value != 0>; 485 static_assert(brigand::size<NumericTypeList>::value == 0 || brigand::size<NumericTypeList>::value == 1, "There can be 0 or 1 numeric types in an IDLUnion."); 486 487 using StringTypeList = brigand::find<TypeList, std::is_base_of<IDLString, brigand::_1>>; 488 using StringType = ConditionalFront<StringTypeList, brigand::size<StringTypeList>::value != 0>; 489 static_assert(brigand::size<StringTypeList>::value == 0 || brigand::size<StringTypeList>::value == 1, "There can be 0 or 1 string types in an IDLUnion."); 479 using NumericTypeList = brigand::filter<TypeList, IsIDLNumber<brigand::_1>>; 480 static constexpr size_t numberOfNumericTypes = brigand::size<NumericTypeList>::value; 481 static_assert(numberOfNumericTypes == 0 || numberOfNumericTypes == 1, "There can be 0 or 1 numeric types in an IDLUnion."); 482 using NumericType = ConditionalFront<NumericTypeList, numberOfNumericTypes != 0>; 483 484 // FIXME: This should also check for IDLEnumeration<T>. 485 using StringTypeList = brigand::filter<TypeList, std::is_base_of<IDLString, brigand::_1>>; 486 static constexpr size_t numberOfStringTypes = brigand::size<StringTypeList>::value; 487 static_assert(numberOfStringTypes == 0 || numberOfStringTypes == 1, "There can be 0 or 1 string types in an IDLUnion."); 488 using StringType = ConditionalFront<StringTypeList, numberOfStringTypes != 0>; 489 490 using SequenceTypeList = brigand::filter<TypeList, IsIDLSequence<brigand::_1>>; 491 static constexpr size_t numberOfSequenceTypes = brigand::size<SequenceTypeList>::value; 492 static_assert(numberOfSequenceTypes == 0 || numberOfSequenceTypes == 1, "There can be 0 or 1 sequence types in an IDLUnion."); 493 using SequenceType = ConditionalFront<SequenceTypeList, numberOfSequenceTypes != 0>; 494 495 using FrozenArrayTypeList = brigand::filter<TypeList, IsIDLFrozenArray<brigand::_1>>; 496 static constexpr size_t numberOfFrozenArrayTypes = brigand::size<FrozenArrayTypeList>::value; 497 static_assert(numberOfFrozenArrayTypes == 0 || numberOfFrozenArrayTypes == 1, "There can be 0 or 1 FrozenArray types in an IDLUnion."); 498 using FrozenArrayType = ConditionalFront<FrozenArrayTypeList, numberOfFrozenArrayTypes != 0>; 499 500 using DictionaryTypeList = brigand::filter<TypeList, IsIDLDictionary<brigand::_1>>; 501 static constexpr size_t numberOfDictionaryTypes = brigand::size<DictionaryTypeList>::value; 502 static_assert(numberOfDictionaryTypes == 0 || numberOfDictionaryTypes == 1, "There can be 0 or 1 dictionary types in an IDLUnion."); 503 using DictionaryType = ConditionalFront<DictionaryTypeList, numberOfDictionaryTypes != 0>; 504 505 static constexpr bool hasObjectType = (numberOfSequenceTypes + numberOfFrozenArrayTypes + numberOfDictionaryTypes) > 0; 490 506 491 507 using InterfaceTypeList = brigand::filter<TypeList, IsIDLInterface<brigand::_1>>; … … 506 522 507 523 // 3. If V is null or undefined, and types includes a dictionary type, then return the result of converting V to that dictionary type. 508 constexpr bool hasDictionaryType = brigand::size<DictionaryTypeList>::value!= 0;524 constexpr bool hasDictionaryType = numberOfDictionaryTypes != 0; 509 525 if (hasDictionaryType) { 510 526 if (value.isUndefinedOrNull()) … … 536 552 } 537 553 538 // FIXME: Add support for steps 5 - 12. 539 554 // FIXME: Add support for steps 5 - 11. 555 556 // 12. If V is any kind of object except for a native RegExp object, then: 557 if (hasObjectType) { 558 if (value.isCell()) { 559 JSC::JSCell* cell = value.asCell(); 560 if (cell->isObject() && cell->type() != JSC::RegExpObjectType) { 561 // FIXME: We should be able to optimize the following code by making use 562 // of the fact that we have proved that the value is an object. 563 564 // 1. If types includes a sequence type, then: 565 // 1. Let method be the result of GetMethod(V, @@iterator). 566 // 2. ReturnIfAbrupt(method). 567 // 3. If method is not undefined, return the result of creating a 568 // sequence of that type from V and method. 569 constexpr bool hasSequenceType = numberOfSequenceTypes != 0; 570 if (hasSequenceType) { 571 bool hasIterator = hasIteratorMethod(state, value); 572 RETURN_IF_EXCEPTION(scope, ReturnType()); 573 if (hasIterator) 574 return std::move<WTF::CheckMoveParameter>(ConditionalConverter<ReturnType, SequenceType, hasSequenceType>::convert(state, value).value()); 575 } 576 577 // 2. If types includes a frozen array type, then: 578 // 1. Let method be the result of GetMethod(V, @@iterator). 579 // 2. ReturnIfAbrupt(method). 580 // 3. If method is not undefined, return the result of creating a 581 // frozen array of that type from V and method. 582 constexpr bool hasFrozenArrayType = numberOfFrozenArrayTypes != 0; 583 if (hasFrozenArrayType) { 584 bool hasIterator = hasIteratorMethod(state, value); 585 RETURN_IF_EXCEPTION(scope, ReturnType()); 586 if (hasIterator) 587 return std::move<WTF::CheckMoveParameter>(ConditionalConverter<ReturnType, FrozenArrayType, hasFrozenArrayType>::convert(state, value).value()); 588 } 589 590 // 3. If types includes a dictionary type, then return the result of 591 // converting V to that dictionary type. 592 if (hasDictionaryType) 593 return std::move<WTF::CheckMoveParameter>(ConditionalConverter<ReturnType, DictionaryType, hasDictionaryType>::convert(state, value).value()); 594 595 // 4. If types includes a record type, then return the result of converting V to that record type. 596 // (FIXME: Add support for record types and step 12.4) 597 // 5. If types includes a callback interface type, then return the result of converting V to that interface type. 598 // (FIXME: Add support for callback interface type and step 12.5) 599 // 6. If types includes object, then return the IDL value that is a reference to the object V. 600 // (FIXME: Add support for object and step 12.6) 601 } 602 } 603 } 604 540 605 // 13. If V is a Boolean value, then: 541 606 // 1. If types includes a boolean, then return the result of converting V to boolean. -
trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm
r207521 r207575 1009 1009 } 1010 1010 if ($defaultValue eq "null") { 1011 return "Nullopt" if $signature->idlType->isUnion; 1011 if ($signature->idlType->isUnion) { 1012 return "Nullopt" if $signature->idlType->isNullable; 1013 1014 my $IDLType = GetIDLType($interface, $signature->idlType); 1015 return "convert<${IDLType}>(state, jsNull());"; 1016 } 1012 1017 return "jsNull()" if $signature->type eq "any"; 1013 1018 return "nullptr" if $codeGenerator->IsWrapperType($signature->type) || $codeGenerator->IsTypedArrayType($signature->type); … … 4365 4370 $value = $shouldPassByReference ? "$name.releaseNonNull()" : "WTFMove($name)"; 4366 4371 } elsif ($codeGenerator->IsDictionaryType($type)) { 4367 $value = "${name} .value()";4372 $value = "${name}"; 4368 4373 } 4369 4374 } … … 5764 5769 push(@constructorArgList, "*" . $parameter->name); 5765 5770 } elsif ($codeGenerator->IsDictionaryType($parameter->type)) { 5766 push(@constructorArgList, $parameter->name . ".value()");5771 push(@constructorArgList, $parameter->name); 5767 5772 } else { 5768 5773 push(@constructorArgList, "WTFMove(" . $parameter->name . ")"); -
trunk/Source/WebCore/bindings/scripts/test/JS/JSTestEventConstructor.cpp
r207498 r207575 132 132 auto eventInitDict = convert<IDLDictionary<TestEventConstructor::Init>>(*state, state->argument(1)); 133 133 RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); 134 auto object = TestEventConstructor::create(WTFMove(type), eventInitDict .value());134 auto object = TestEventConstructor::create(WTFMove(type), eventInitDict); 135 135 return JSValue::encode(toJSNewlyCreated(state, castedThis->globalObject(), WTFMove(object))); 136 136 } -
trunk/Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp
r207519 r207575 7711 7711 auto init = convert<IDLDictionary<TestObj::Dictionary>>(*state, state->uncheckedArgument(0)); 7712 7712 RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); 7713 impl.attachShadowRoot(init .value());7713 impl.attachShadowRoot(init); 7714 7714 return JSValue::encode(jsUndefined()); 7715 7715 } … … 7731 7731 auto dict = convert<IDLDictionary<DictionaryImplName>>(*state, state->uncheckedArgument(0)); 7732 7732 RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); 7733 impl.operationWithExternalDictionaryParameter(dict .value());7733 impl.operationWithExternalDictionaryParameter(dict); 7734 7734 return JSValue::encode(jsUndefined()); 7735 7735 } -
trunk/Source/WebCore/testing/TypeConversions.h
r204215 r207575 27 27 #define TypeConversions_h 28 28 29 #include "Node.h" 29 30 #include <wtf/FastMalloc.h> 30 31 #include <wtf/RefCounted.h> 32 #include <wtf/Variant.h> 33 #include <wtf/Vector.h> 31 34 #include <wtf/text/WTFString.h> 32 35 … … 36 39 public: 37 40 static Ref<TypeConversions> create() { return adoptRef(*new TypeConversions()); } 41 42 enum class UnionType { 43 Node, 44 Sequence, 45 Dictionary 46 }; 47 48 struct OtherDictionary { 49 int longValue; 50 String stringValue; 51 }; 52 53 struct Dictionary { 54 int longValue; 55 String stringValue; 56 Vector<String> sequenceValue; 57 Variant<RefPtr<Node>, Vector<String>, OtherDictionary> unionValue; 58 }; 38 59 39 60 long testLong() { return m_long; } … … 78 99 void setTestUSVString(const String& usvstring) { m_usvstring = usvstring; } 79 100 101 void setTypeConversionsDictionary(Dictionary& dictionary) 102 { 103 m_typeConversionsDictionaryLongValue = dictionary.longValue; 104 m_typeConversionsDictionaryStringValue = dictionary.stringValue; 105 m_typeConversionsDictionarySequenceValue = dictionary.sequenceValue; 106 m_typeConversionsDictionaryUnionValue = dictionary.unionValue; 107 } 108 109 int typeConversionsDictionaryLongValue() { return m_typeConversionsDictionaryLongValue; } 110 String typeConversionsDictionaryStringValue() { return m_typeConversionsDictionaryStringValue; } 111 Vector<String> typeConversionsDictionarySequenceValue() { return m_typeConversionsDictionarySequenceValue; } 112 UnionType typeConversionsDictionaryUnionType() 113 { 114 return WTF::visit(WTF::makeVisitor( 115 [](const RefPtr<Node>&) -> UnionType { return UnionType::Node; }, 116 [](const Vector<String>&) -> UnionType { return UnionType::Sequence; }, 117 [](const OtherDictionary&) -> UnionType { return UnionType::Dictionary; } 118 ), m_typeConversionsDictionaryUnionValue); 119 } 120 80 121 private: 81 122 TypeConversions() … … 83 124 } 84 125 85 long m_long ;86 unsigned long m_unsignedLong ;87 long long m_longLong ;88 unsigned long long m_unsignedLongLong ;89 int8_t m_byte ;90 uint8_t m_octet ;91 int16_t m_short ;92 uint16_t m_UnsignedShort ;126 long m_long { 0 }; 127 unsigned long m_unsignedLong { 0 }; 128 long long m_longLong { 0 }; 129 unsigned long long m_unsignedLongLong { 0 }; 130 int8_t m_byte { 0 }; 131 uint8_t m_octet { 0 }; 132 int16_t m_short { 0 }; 133 uint16_t m_UnsignedShort { 0 }; 93 134 String m_string; 94 135 String m_usvstring; 136 137 int m_typeConversionsDictionaryLongValue { 0 }; 138 String m_typeConversionsDictionaryStringValue; 139 Vector<String> m_typeConversionsDictionarySequenceValue; 140 Variant<RefPtr<Node>, Vector<String>, OtherDictionary> m_typeConversionsDictionaryUnionValue; 95 141 }; 96 142 -
trunk/Source/WebCore/testing/TypeConversions.idl
r204215 r207575 23 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 24 */ 25 26 enum UnionType { "node", "sequence", "dictionary" }; 25 27 26 28 [ … … 51 53 attribute DOMString testString; 52 54 attribute USVString testUSVString; 55 56 void setTypeConversionsDictionary(TypeConversionsDictionary d); 57 readonly attribute long typeConversionsDictionaryLongValue; 58 readonly attribute DOMString typeConversionsDictionaryStringValue; 59 readonly attribute sequence<DOMString> typeConversionsDictionarySequenceValue; 60 readonly attribute UnionType typeConversionsDictionaryUnionType; 53 61 }; 62 63 dictionary TypeConversionsOtherDictionary { 64 long longValue = 0; 65 DOMString stringValue = ""; 66 }; 67 68 dictionary TypeConversionsDictionary { 69 long longValue = 0; 70 DOMString stringValue = ""; 71 sequence<DOMString> sequenceValue = []; 72 (Node or sequence<DOMString> or TypeConversionsOtherDictionary) unionValue = null; 73 };
Note: See TracChangeset
for help on using the changeset viewer.