[WebIDL/DOM] Remove need for custom bindings for HTMLAllCollection and bring up to...
authorweinig@apple.com <weinig@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 15 May 2017 01:09:48 +0000 (01:09 +0000)
committerweinig@apple.com <weinig@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 15 May 2017 01:09:48 +0000 (01:09 +0000)
https://bugs.webkit.org/show_bug.cgi?id=172095

Reviewed by Darin Adler.

LayoutTests/imported/w3c:

* web-platform-tests/html/infrastructure/common-dom-interfaces/collections/htmlallcollection-expected.txt:
Update results.

Source/WebCore:

- Adds support for the legacycaller WebIDL special annotation.
- Updates implementation of HTMLAllCollection to match the current HTML spec.

Test: fast/dom/document-all.html

* CMakeLists.txt:
* WebCore.xcodeproj/project.pbxproj:
* bindings/js/JSBindingsAllInOne.cpp:
* bindings/js/JSHTMLAllCollectionCustom.cpp: Removed.
Removed JSHTMLAllCollectionCustom.cpp

* bindings/scripts/CodeGeneratorJS.pm:
(GenerateInterface):
(AddLegacyCallerOperationIfNeeded):
Before code generation, clone all the legacycaller operations and put them
in their own set, so they can form an overload set.

(AddStringifierOperationIfNeeded):
Use IDLParser::cloneType as the FIXME suggested.

(GenerateHeader):
Group call related functionality together and use new IsCallable predicate.

(GenerateOverloadedFunctionOrConstructor):
Generalize a little bit to allow the function being overloaded to be an overloaded legacycaller.

(GenerateImplementation):
Add call to generate the legacycaller code.

(GenerateLegacyCallerDefinitions):
(GenerateLegacyCallerDefinition):
Generate the legacycaller definition, using GenerateArgumentsCountCheck, GenerateParametersCheck
and GenerateImplementationFunctionCall to do all the heavy lifting.

(IsCallable):
Add helper predicate for both custom calls and legacycaller.

* bindings/scripts/IDLParser.pm:
(cloneType):.
(cloneArgument):.
(cloneOperation):
Add cloning functions for IDLArgument and IDLOperation, and make IDLType's
clone feasible for calling outside the package by removing the unneeded
self parameter.

* bindings/scripts/test/JS/JSTestObj.cpp
* bindings/scripts/test/JS/JSTestObj.h
* bindings/scripts/test/TestObj.idl:
Add testing of legacycaller overloading.

* dom/Document.cpp:
(WebCore::Document::allFilteredByName):
* dom/Document.h:
Add new collection access for the HTMLAllNamedSubCollection.

* html/CachedHTMLCollection.h:
(WebCore::nameShouldBeVisibleInDocumentAll):
Update list of tags to match the current spec.

* html/CollectionType.h:
Add new type for HTMLAllNamedSubCollection.

* html/GenericCachedHTMLCollection.cpp:
(WebCore::GenericCachedHTMLCollection<traversalType>::elementMatches):
Specify that DocumentAllNamedItems does not want
the default elementMatches.

* html/HTMLAllCollection.cpp:
(WebCore::HTMLAllCollection::namedOrIndexedItemOrItems):
(WebCore::HTMLAllCollection::namedItemOrItems):
(WebCore::HTMLAllNamedSubCollection::~HTMLAllNamedSubCollection):
(WebCore::HTMLAllNamedSubCollection::elementMatches):
* html/HTMLAllCollection.h:
Move implementations from the custom binding, and re-implement to
match the spec. Alternate names to item/namedItem were needed to not
shadow the existing ones in HTMLCollection. HTMLAllNamedSubCollection
is a simple HTMLCollection that matches on a name, following the rules
of document.all about which tags can have name attributes.

* html/HTMLAllCollection.idl:
Remove custom annotations and add legacycaller which is now supported.

* html/HTMLCollection.cpp:
(WebCore::invalidationTypeExcludingIdAndNameAttributes):
(WebCore::HTMLCollection::~HTMLCollection):
Add DocumentAllNamedItems.

LayoutTests:

* fast/dom/collection-null-like-arguments-expected.txt:
Update results.

* fast/dom/document-all-expected.txt: Added.
* fast/dom/document-all.html: Added.
New test that covers a bunch of missing coverage.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@216851 268f45cc-cd09-0410-ab3c-d52691b4dbfc

25 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/dom/collection-null-like-arguments-expected.txt
LayoutTests/fast/dom/document-all-expected.txt [new file with mode: 0644]
LayoutTests/fast/dom/document-all.html [new file with mode: 0644]
LayoutTests/imported/w3c/ChangeLog
LayoutTests/imported/w3c/web-platform-tests/html/infrastructure/common-dom-interfaces/collections/htmlallcollection-expected.txt
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/bindings/js/JSBindingsAllInOne.cpp
Source/WebCore/bindings/js/JSHTMLAllCollectionCustom.cpp [deleted file]
Source/WebCore/bindings/scripts/CodeGeneratorJS.pm
Source/WebCore/bindings/scripts/IDLParser.pm
Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp
Source/WebCore/bindings/scripts/test/JS/JSTestObj.h
Source/WebCore/bindings/scripts/test/TestObj.idl
Source/WebCore/dom/Document.cpp
Source/WebCore/dom/Document.h
Source/WebCore/html/CachedHTMLCollection.h
Source/WebCore/html/CollectionType.h
Source/WebCore/html/GenericCachedHTMLCollection.cpp
Source/WebCore/html/HTMLAllCollection.cpp
Source/WebCore/html/HTMLAllCollection.h
Source/WebCore/html/HTMLAllCollection.idl
Source/WebCore/html/HTMLCollection.cpp

index 0607245..d164a59 100644 (file)
@@ -1,3 +1,17 @@
+2017-05-14  Sam Weinig  <sam@webkit.org>
+
+        [WebIDL/DOM] Remove need for custom bindings for HTMLAllCollection and bring up to spec
+        https://bugs.webkit.org/show_bug.cgi?id=172095
+
+        Reviewed by Darin Adler.
+
+        * fast/dom/collection-null-like-arguments-expected.txt:
+        Update results.
+
+        * fast/dom/document-all-expected.txt: Added.
+        * fast/dom/document-all.html: Added.
+        New test that covers a bunch of missing coverage.
+
 2017-05-14  David Kilzer  <ddkilzer@apple.com>
 
         [iOS/macOS Debug WK2] LayoutTests/imported/w3c/web-platform-tests/webrtc/interfaces.html is a flaky crash due to assertion failure
index 1170658..43d9057 100644 (file)
@@ -7,19 +7,19 @@ document.all(0):      [object HTMLHtmlElement]
 document.all.item(0): [object HTMLHtmlElement]
 
 document.all[""]:      undefined
-document.all(""):      undefined
-document.all.item(""): undefined
+document.all(""):      null
+document.all.item(""): null
 
 document.all["0"]:      [object HTMLHtmlElement]
 document.all("0"):      [object HTMLHtmlElement]
 document.all.item("0"): [object HTMLHtmlElement]
 
 document.all[undefined]:      undefined
-document.all(undefined):      undefined
-document.all.item(undefined): undefined
+document.all(undefined):      null
+document.all.item(undefined): null
 
 document.all[null]:      undefined
-document.all(null):      undefined
-document.all.item(null): undefined
+document.all(null):      null
+document.all.item(null): null
 
 
diff --git a/LayoutTests/fast/dom/document-all-expected.txt b/LayoutTests/fast/dom/document-all-expected.txt
new file mode 100644 (file)
index 0000000..7a93eb7
--- /dev/null
@@ -0,0 +1,47 @@
+Tests document.all
+
+
+PASS document.all's index getter returns all the elements in document order 
+PASS document.all's index getter returns undefined for indexes greater than length 
+PASS document.all's index getter returns undefined for indexes less than zero 
+PASS document.all's name attribute accessing works for a 
+PASS document.all's name attribute accessing works for applet 
+PASS document.all's name attribute accessing works for button 
+PASS document.all's name attribute accessing works for embed 
+PASS document.all's name attribute accessing works for form 
+PASS document.all's name attribute accessing works for frame 
+PASS document.all's name attribute accessing works for frameset 
+PASS document.all's name attribute accessing works for iframe 
+PASS document.all's name attribute accessing works for img 
+PASS document.all's name attribute accessing works for input 
+PASS document.all's name attribute accessing works for map 
+PASS document.all's name attribute accessing works for meta 
+PASS document.all's name attribute accessing works for object 
+PASS document.all's name attribute accessing works for select 
+PASS document.all's name attribute accessing works for textarea 
+PASS document.all's name attribute accessing doesn't work for div 
+PASS document.all's name attribute accessing doesn't work for span 
+PASS document.all's id attribute accessing works for a 
+PASS document.all's id attribute accessing works for applet 
+PASS document.all's id attribute accessing works for button 
+PASS document.all's id attribute accessing works for embed 
+PASS document.all's id attribute accessing works for form 
+PASS document.all's id attribute accessing works for frame 
+PASS document.all's id attribute accessing works for frameset 
+PASS document.all's id attribute accessing works for iframe 
+PASS document.all's id attribute accessing works for img 
+PASS document.all's id attribute accessing works for input 
+PASS document.all's id attribute accessing works for map 
+PASS document.all's id attribute accessing works for meta 
+PASS document.all's id attribute accessing works for object 
+PASS document.all's id attribute accessing works for select 
+PASS document.all's id attribute accessing works for textarea 
+PASS document.all's id attribute accessing works for div 
+PASS document.all's id attribute accessing works for span 
+PASS document.all will return a sub-collection if the name/id is found more than once 
+PASS document.all will return a sub-collection if the name/id is found more than once, but still adheres to the rules about what tags can have names 
+PASS document.all will return a sub-collection if the name/id is found more than once, that is live 
+PASS document.all's namedItem function requires passing an argument 
+PASS document.all's item function and legacy caller functionality allow passing no arguments 
+PASS document.all's item function and legacy caller functionality will try to convert their DOMString argument to an index before name lookup 
+
diff --git a/LayoutTests/fast/dom/document-all.html b/LayoutTests/fast/dom/document-all.html
new file mode 100644 (file)
index 0000000..556abe2
--- /dev/null
@@ -0,0 +1,179 @@
+<!DOCTYPE html>
+<head>
+    <title>document.all</title>
+<body>
+<p>Tests document.all</p>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script>
+
+let validNamedElementTags = ['a', 'applet', 'button', 'embed', 'form', 'frame', 'frameset', 'iframe', 'img', 'input', 'map', 'meta', 'object', 'select', 'textarea'];
+let invalidNamedElementTags = ['div', 'span'];
+let validAnInvalidNamedElementTags = validNamedElementTags.concat(invalidNamedElementTags);
+
+let playground = document.createElement('div');
+document.body.append(playground);
+
+test(function() {
+    assert_equals(document.all[0], document.documentElement);
+    assert_equals(document.all[1], document.head);
+    assert_equals(document.all[2], document.head.firstElementChild);
+}, "document.all's index getter returns all the elements in document order");
+
+test(function() {
+    assert_equals(document.all[document.all.length + 1], undefined);
+}, "document.all's index getter returns undefined for indexes greater than length");
+
+test(function() {
+    assert_equals(document.all[-1], undefined);
+}, "document.all's index getter returns undefined for indexes less than zero");
+
+for (let elementTag of validNamedElementTags) {
+    test(function() {
+        let element = document.createElement(elementTag);
+        element.setAttribute("name", "testName");
+        playground.append(element);
+    
+        assert_equals(document.all.namedItem('testName'), element);
+        assert_equals(document.all['testName'], element);
+        assert_equals(document.all.item('testName'), element);
+        assert_equals(document.all('testName'), element);
+    
+        element.remove();
+    }, "document.all's name attribute accessing works for " + elementTag);
+}
+
+for (let elementTag of invalidNamedElementTags) {
+    test(function() {
+        let element = document.createElement(elementTag);
+        element.setAttribute("name", "testName");
+        playground.append(element);
+    
+        assert_equals(document.all.namedItem('testName'), null);
+        assert_equals(document.all['testName'], undefined);
+        assert_equals(document.all.item('testName'), null);
+        assert_equals(document.all('testName'), null);
+    
+        element.remove();
+    }, "document.all's name attribute accessing doesn't work for " + elementTag);
+}
+
+for (let elementTag of validAnInvalidNamedElementTags) {
+    test(function() {
+        let element = document.createElement(elementTag);
+        element.setAttribute("id", "testId");
+        playground.append(element);
+    
+        assert_equals(document.all.namedItem('testId'), element);
+        assert_equals(document.all['testId'], element);
+        assert_equals(document.all.item('testId'), element);
+        assert_equals(document.all('testId'), element);
+    
+        element.remove();
+    }, "document.all's id attribute accessing works for " + elementTag);
+}
+
+test(function() {
+    let element1 = document.createElement('button');
+    element1.setAttribute("name", "test");
+    playground.append(element1);
+
+    let element2 = document.createElement('span');
+    element2.setAttribute("id", "test");
+    playground.append(element2);
+
+    assert_equals(document.all.namedItem('test').length, 2);
+    assert_equals(document.all['test'].length, 2);
+    assert_equals(document.all.item('test').length, 2);
+    assert_equals(document.all('test').length, 2);
+    assert_class_string(document.all.namedItem('test'), "HTMLCollection");
+    assert_class_string(document.all['test'], "HTMLCollection");
+    assert_class_string(document.all.item('test'), "HTMLCollection");
+    assert_class_string(document.all('test'), "HTMLCollection");
+
+    element1.remove();
+    element2.remove();
+}, "document.all will return a sub-collection if the name/id is found more than once");
+
+test(function() {
+    let element1 = document.createElement('button');
+    element1.setAttribute("name", "test");
+    playground.append(element1);
+
+    let element2 = document.createElement('span');
+    element2.setAttribute("id", "test");
+    playground.append(element2);
+
+    let element3 = document.createElement('span');
+    element3.setAttribute("name", "test");
+    playground.append(element2);
+
+    assert_equals(document.all.namedItem('test').length, 2);
+    assert_equals(document.all['test'].length, 2);
+    assert_equals(document.all.item('test').length, 2);
+    assert_equals(document.all('test').length, 2);
+    assert_equals(document.all.namedItem('test')[0], element1);
+    assert_equals(document.all.namedItem('test')[1], element2);
+    assert_equals(document.all['test'][0], element1);
+    assert_equals(document.all['test'][1], element2);
+    assert_equals(document.all.item('test')[0], element1);
+    assert_equals(document.all.item('test')[1], element2);
+    assert_equals(document.all('test')[0], element1);
+    assert_equals(document.all('test')[1], element2);
+
+    element1.remove();
+    element2.remove();
+    element3.remove();
+}, "document.all will return a sub-collection if the name/id is found more than once, but still adheres to the rules about what tags can have names");
+
+test(function() {
+    let element1 = document.createElement('button');
+    element1.setAttribute("name", "test");
+    playground.append(element1);
+
+    let element2 = document.createElement('span');
+    element2.setAttribute("id", "test");
+    playground.append(element2);
+
+    let collection = document.all.namedItem('test');
+    assert_equals(collection.length, 2);
+
+    let element3 = document.createElement('img');
+    element3.setAttribute("name", "test");
+    playground.append(element3);
+
+    assert_equals(collection.length, 3);
+
+    element1.remove();
+    element2.remove();
+
+    assert_equals(collection.length, 1);
+
+    element3.remove();
+}, "document.all will return a sub-collection if the name/id is found more than once, that is live");
+
+test(function() {
+    assert_throws(new TypeError(), function() { document.all.namedItem() });
+}, "document.all's namedItem function requires passing an argument");
+
+test(function() {
+    assert_equals(document.all.item(), null);
+    assert_equals(document.all(), null);
+}, "document.all's item function and legacy caller functionality allow passing no arguments");
+
+test(function() {
+    let element = document.createElement('button');
+    element.setAttribute("name", "0");
+    playground.append(element);
+
+    assert_equals(document.all.item('0'), document.documentElement);
+    assert_equals(document.all('0'), document.documentElement);
+    assert_equals(document.all.namedItem('0'), element);
+
+    element.remove();
+}, "document.all's item function and legacy caller functionality will try to convert their DOMString argument to an index before name lookup");
+
+playground.remove();
+
+</script>
+</body>
index 307ab69..9737cba 100644 (file)
@@ -1,3 +1,13 @@
+2017-05-14  Sam Weinig  <sam@webkit.org>
+
+        [WebIDL/DOM] Remove need for custom bindings for HTMLAllCollection and bring up to spec
+        https://bugs.webkit.org/show_bug.cgi?id=172095
+
+        Reviewed by Darin Adler.
+
+        * web-platform-tests/html/infrastructure/common-dom-interfaces/collections/htmlallcollection-expected.txt:
+        Update results.
+
 2017-05-12  Romain Bellessort  <romain.bellessort@crf.canon.fr>
 
         [Readable Streams API] Add ReadableStreamBYOBReader closed getter
index d80969f..85fa17f 100644 (file)
@@ -10,5 +10,5 @@ PASS Test lookup IMG in collection using []
 PASS Test lookup IMG in collection using . 
 PASS Test lookup tags in collection using . 
 PASS Should find root element too 
-FAIL Should find both anchors and produce a list undefined is not an object (evaluating 'document.all["foo"].length')
+PASS Should find both anchors and produce a list 
 
index b9a9dbf..4b10778 100644 (file)
@@ -1168,7 +1168,6 @@ set(WebCore_SOURCES
     bindings/js/JSEventListener.cpp
     bindings/js/JSEventTargetCustom.cpp
     bindings/js/JSExceptionBase.cpp
-    bindings/js/JSHTMLAllCollectionCustom.cpp
     bindings/js/JSHTMLAppletElementCustom.cpp
     bindings/js/JSHTMLCanvasElementCustom.cpp
     bindings/js/JSHTMLCollectionCustom.cpp
index 85db67a..a78231e 100644 (file)
@@ -1,3 +1,97 @@
+2017-05-14  Sam Weinig  <sam@webkit.org>
+
+        [WebIDL/DOM] Remove need for custom bindings for HTMLAllCollection and bring up to spec
+        https://bugs.webkit.org/show_bug.cgi?id=172095
+
+        Reviewed by Darin Adler.
+
+        - Adds support for the legacycaller WebIDL special annotation.
+        - Updates implementation of HTMLAllCollection to match the current HTML spec.
+
+        Test: fast/dom/document-all.html
+
+        * CMakeLists.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * bindings/js/JSBindingsAllInOne.cpp:
+        * bindings/js/JSHTMLAllCollectionCustom.cpp: Removed.
+        Removed JSHTMLAllCollectionCustom.cpp
+
+        * bindings/scripts/CodeGeneratorJS.pm:
+        (GenerateInterface):
+        (AddLegacyCallerOperationIfNeeded):
+        Before code generation, clone all the legacycaller operations and put them
+        in their own set, so they can form an overload set.
+        
+        (AddStringifierOperationIfNeeded):
+        Use IDLParser::cloneType as the FIXME suggested.
+
+        (GenerateHeader):
+        Group call related functionality together and use new IsCallable predicate.
+
+        (GenerateOverloadedFunctionOrConstructor):
+        Generalize a little bit to allow the function being overloaded to be an overloaded legacycaller.
+
+        (GenerateImplementation):
+        Add call to generate the legacycaller code.
+
+        (GenerateLegacyCallerDefinitions):
+        (GenerateLegacyCallerDefinition):
+        Generate the legacycaller definition, using GenerateArgumentsCountCheck, GenerateParametersCheck
+        and GenerateImplementationFunctionCall to do all the heavy lifting.
+
+        (IsCallable):
+        Add helper predicate for both custom calls and legacycaller.
+
+        * bindings/scripts/IDLParser.pm:
+        (cloneType):.
+        (cloneArgument):.
+        (cloneOperation):
+        Add cloning functions for IDLArgument and IDLOperation, and make IDLType's
+        clone feasible for calling outside the package by removing the unneeded 
+        self parameter.
+
+        * bindings/scripts/test/JS/JSTestObj.cpp
+        * bindings/scripts/test/JS/JSTestObj.h
+        * bindings/scripts/test/TestObj.idl:
+        Add testing of legacycaller overloading.
+
+        * dom/Document.cpp:
+        (WebCore::Document::allFilteredByName):
+        * dom/Document.h:
+        Add new collection access for the HTMLAllNamedSubCollection.
+
+        * html/CachedHTMLCollection.h:
+        (WebCore::nameShouldBeVisibleInDocumentAll):
+        Update list of tags to match the current spec.
+
+        * html/CollectionType.h:
+        Add new type for HTMLAllNamedSubCollection.
+
+        * html/GenericCachedHTMLCollection.cpp:
+        (WebCore::GenericCachedHTMLCollection<traversalType>::elementMatches):
+        Specify that DocumentAllNamedItems does not want
+        the default elementMatches.
+        * html/HTMLAllCollection.cpp:
+        (WebCore::HTMLAllCollection::namedOrIndexedItemOrItems):
+        (WebCore::HTMLAllCollection::namedItemOrItems):
+        (WebCore::HTMLAllNamedSubCollection::~HTMLAllNamedSubCollection):
+        (WebCore::HTMLAllNamedSubCollection::elementMatches):
+        * html/HTMLAllCollection.h:
+        Move implementations from the custom binding, and re-implement to
+        match the spec. Alternate names to item/namedItem were needed to not
+        shadow the existing ones in HTMLCollection. HTMLAllNamedSubCollection
+        is a simple HTMLCollection that matches on a name, following the rules
+        of document.all about which tags can have name attributes.
+
+        * html/HTMLAllCollection.idl:
+        Remove custom annotations and add legacycaller which is now supported.
+
+        * html/HTMLCollection.cpp:
+        (WebCore::invalidationTypeExcludingIdAndNameAttributes):
+        (WebCore::HTMLCollection::~HTMLCollection):
+        Add DocumentAllNamedItems.
+
 2017-05-14  Zalan Bujtas  <zalan@apple.com>
 
         Remove unused lambda in TextFragmentIterator::TextFragment::split() and cleanup dependencies.
index 610b539..a178bcb 100644 (file)
                BC97E23B109144950010D361 /* HTMLAllCollection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC97E239109144950010D361 /* HTMLAllCollection.cpp */; };
                BC97E412109154FA0010D361 /* JSHTMLAllCollection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC97E410109154FA0010D361 /* JSHTMLAllCollection.cpp */; };
                BC97E413109154FA0010D361 /* JSHTMLAllCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = BC97E411109154FA0010D361 /* JSHTMLAllCollection.h */; };
-               BC97E42C10915B060010D361 /* JSHTMLAllCollectionCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC97E42B10915B060010D361 /* JSHTMLAllCollectionCustom.cpp */; };
                BC98A27D0C0C9950004BEBF7 /* JSStyleSheetCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC98A27C0C0C9950004BEBF7 /* JSStyleSheetCustom.cpp */; };
                BCA169A20BFD55B40019CA76 /* JSHTMLTableCaptionElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCA169A00BFD55B40019CA76 /* JSHTMLTableCaptionElement.cpp */; };
                BCA169A30BFD55B40019CA76 /* JSHTMLTableCaptionElement.h in Headers */ = {isa = PBXBuildFile; fileRef = BCA169A10BFD55B40019CA76 /* JSHTMLTableCaptionElement.h */; };
                BC97E23C109146F10010D361 /* HTMLAllCollection.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = HTMLAllCollection.idl; sourceTree = "<group>"; };
                BC97E410109154FA0010D361 /* JSHTMLAllCollection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSHTMLAllCollection.cpp; sourceTree = "<group>"; };
                BC97E411109154FA0010D361 /* JSHTMLAllCollection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSHTMLAllCollection.h; sourceTree = "<group>"; };
-               BC97E42B10915B060010D361 /* JSHTMLAllCollectionCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSHTMLAllCollectionCustom.cpp; sourceTree = "<group>"; };
                BC98A27C0C0C9950004BEBF7 /* JSStyleSheetCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSStyleSheetCustom.cpp; sourceTree = "<group>"; };
                BC9A6141146859D9006057FD /* DOMExceptions.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = DOMExceptions.in; sourceTree = "<group>"; };
                BC9A6142146859D9006057FD /* EventNames.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = EventNames.in; sourceTree = "<group>"; };
                                51E269321DD3BC43006B6A58 /* JSIDBTransactionCustom.cpp */,
                                A7D0318D0E93540300E24ACD /* JSImageDataCustom.cpp */,
                                AD726FE716D9F204003A4E6D /* JSMediaListCustom.h */,
+                               415CDAF61E6CE0D3004F11EE /* JSMediaStreamTrackCustom.cpp */,
                                E1A5F99A0E7EAA2500AF85EA /* JSMessageChannelCustom.cpp */,
                                E1ADED460E76B8DD004A1A5E /* JSMessagePortCustom.cpp */,
                                1A750DD30A90E729000FF215 /* JSNodeIteratorCustom.cpp */,
                                C28083411C6DC96A001451B6 /* JSFontFaceCustom.cpp */,
                                1C24EEAA1C72AA0A0080F8FC /* JSFontFaceSetCustom.cpp */,
                                BCE7B1920D4E86960075A539 /* JSHistoryCustom.cpp */,
-                               BC97E42B10915B060010D361 /* JSHTMLAllCollectionCustom.cpp */,
                                BC4EDEF30C08F3FB007EDD49 /* JSHTMLAppletElementCustom.cpp */,
                                9392262C1032107B006E7D5D /* JSHTMLCanvasElementCustom.cpp */,
                                BC51580A0C03D404008BB0EE /* JSHTMLDocumentCustom.cpp */,
                                7A74ECBC101839DA00BF939E /* JSInspectorFrontendHostCustom.cpp */,
                                BCE1C43F0D9830F4003B02F2 /* JSLocationCustom.cpp */,
                                2D9BF7481DBFDDF8007A7D99 /* JSMediaKeySessionCustom.cpp */,
-                               415CDAF61E6CE0D3004F11EE /* JSMediaStreamTrackCustom.cpp */,
                                410B7E711045FAB000D8224F /* JSMessageEventCustom.cpp */,
                                A1E5B31D1AAD1DA4006EBEFB /* JSMockContentFilterSettingsCustom.cpp */,
                                C6F0917E143A2BB900685849 /* JSMutationObserverCustom.cpp */,
                                57957CB61E972C78008072AB /* JSHkdfParams.cpp in Sources */,
                                57E233691DCAB24300F28D01 /* JSHmacKeyParams.cpp in Sources */,
                                BC97E412109154FA0010D361 /* JSHTMLAllCollection.cpp in Sources */,
-                               BC97E42C10915B060010D361 /* JSHTMLAllCollectionCustom.cpp in Sources */,
                                1A4A2DEF0A1B852A00C807F8 /* JSHTMLAnchorElement.cpp in Sources */,
                                1A4A2DF10A1B852A00C807F8 /* JSHTMLAppletElement.cpp in Sources */,
                                BC4EDEF40C08F3FB007EDD49 /* JSHTMLAppletElementCustom.cpp in Sources */,
index 2604d05..e3bc775 100644 (file)
@@ -67,7 +67,6 @@
 #include "JSEventListener.cpp"
 #include "JSEventTargetCustom.cpp"
 #include "JSExceptionBase.cpp"
-#include "JSHTMLAllCollectionCustom.cpp"
 #include "JSHTMLAppletElementCustom.cpp"
 #include "JSHTMLCanvasElementCustom.cpp"
 #include "JSHTMLCollectionCustom.cpp"
diff --git a/Source/WebCore/bindings/js/JSHTMLAllCollectionCustom.cpp b/Source/WebCore/bindings/js/JSHTMLAllCollectionCustom.cpp
deleted file mode 100644 (file)
index d8286a5..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (C) 2009, 2016 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- */
-
-#include "config.h"
-#include "JSHTMLAllCollection.h"
-
-#include "HTMLAllCollection.h"
-#include "JSNode.h"
-#include "JSNodeList.h"
-#include "StaticNodeList.h"
-#include <runtime/IdentifierInlines.h>
-
-using namespace JSC;
-
-namespace WebCore {
-
-static JSValue namedItems(ExecState& state, JSHTMLAllCollection* collection, PropertyName propertyName)
-{
-    Vector<Ref<Element>> namedItems = collection->wrapped().namedItems(propertyNameToAtomicString(propertyName));
-
-    if (namedItems.isEmpty())
-        return jsUndefined();
-    if (namedItems.size() == 1)
-        return toJS(&state, collection->globalObject(), namedItems[0]);
-
-    // FIXME: HTML5 specification says this should be a HTMLCollection.
-    // http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-interfaces.html#htmlallcollection
-    return toJS(&state, collection->globalObject(), StaticElementList::create(WTFMove(namedItems)));
-}
-
-// HTMLAllCollections are strange objects, they support both get and call.
-static EncodedJSValue JSC_HOST_CALL callHTMLAllCollection(ExecState* exec)
-{
-    VM& vm = exec->vm();
-    auto scope = DECLARE_THROW_SCOPE(vm);
-
-    if (exec->argumentCount() < 1)
-        return JSValue::encode(jsUndefined());
-
-    // Do not use thisObj here. It can be the JSHTMLDocument, in the document.forms(i) case.
-    JSHTMLAllCollection* jsCollection = jsCast<JSHTMLAllCollection*>(exec->jsCallee());
-    HTMLAllCollection& collection = jsCollection->wrapped();
-
-    // Also, do we need the TypeError test here ?
-
-    if (exec->argumentCount() == 1) {
-        // Support for document.all(<index>) etc.
-        String string = exec->argument(0).toWTFString(exec);
-        RETURN_IF_EXCEPTION(scope, encodedJSValue());
-        if (std::optional<uint32_t> index = parseIndex(*string.impl()))
-            return JSValue::encode(toJS(exec, jsCollection->globalObject(), collection.item(index.value())));
-
-        // Support for document.images('<name>') etc.
-        return JSValue::encode(namedItems(*exec, jsCollection, Identifier::fromString(exec, string)));
-    }
-
-    // The second arg, if set, is the index of the item we want
-    String string = exec->argument(0).toWTFString(exec);
-    RETURN_IF_EXCEPTION(scope, encodedJSValue());
-    if (std::optional<uint32_t> index = parseIndex(*exec->argument(1).toWTFString(exec).impl())) {
-        if (auto* item = collection.namedItemWithIndex(string, index.value()))
-            return JSValue::encode(toJS(exec, jsCollection->globalObject(), *item));
-    }
-
-    return JSValue::encode(jsUndefined());
-}
-
-CallType JSHTMLAllCollection::getCallData(JSCell*, CallData& callData)
-{
-    callData.native.function = callHTMLAllCollection;
-    return CallType::Host;
-}
-
-bool JSHTMLAllCollection::nameGetter(ExecState* state, PropertyName propertyName, JSValue& value)
-{
-    JSValue items = namedItems(*state, this, propertyName);
-    if (items.isUndefined())
-        return false;
-
-    value = items;
-    return true;
-}
-
-JSValue JSHTMLAllCollection::item(ExecState& state)
-{
-    VM& vm = state.vm();
-    auto scope = DECLARE_THROW_SCOPE(vm);
-
-    if (UNLIKELY(state.argumentCount() < 1))
-        return throwException(&state, scope, createNotEnoughArgumentsError(&state));
-
-    String argument = state.uncheckedArgument(0).toWTFString(&state);
-    if (std::optional<uint32_t> index = parseIndex(*argument.impl()))
-        return toJS(&state, globalObject(), wrapped().item(index.value()));
-    return namedItems(state, this, Identifier::fromString(&state, argument));
-}
-
-JSValue JSHTMLAllCollection::namedItem(ExecState& state)
-{
-    JSValue value = namedItems(state, this, Identifier::fromString(&state, state.argument(0).toWTFString(&state)));
-    return value.isUndefined() ? jsNull() : value;
-}
-
-} // namespace WebCore
index 02a9541..2389981 100644 (file)
@@ -162,7 +162,9 @@ sub GenerateInterface
     my ($object, $interface, $defines, $enumerations, $dictionaries) = @_;
 
     $codeGenerator->LinkOverloadedFunctions($interface);
+
     AddStringifierOperationIfNeeded($interface);
+    AddLegacyCallerOperationIfNeeded($interface);
 
     if ($interface->isCallback) {
         $object->GenerateCallbackInterfaceHeader($interface, $enumerations, $dictionaries);
@@ -188,10 +190,7 @@ sub AddStringifierOperationIfNeeded
         $stringifier->extendedAttributes($extendedAttributeList);
         die "stringifier can only be used on attributes of String types" unless $codeGenerator->IsStringType($attribute->type);
         
-        # FIXME: This should use IDLParser's cloneType.
-        my $type = IDLType->new();
-        $type->name($attribute->type->name);
-
+        my $type = IDLParser::cloneType($attribute->type);
         $stringifier->type($type);
 
         push(@{$interface->functions}, $stringifier);
@@ -199,6 +198,24 @@ sub AddStringifierOperationIfNeeded
     }
 }
 
+sub AddLegacyCallerOperationIfNeeded
+{
+    my $interface = shift;
+
+    foreach my $operation (@{$interface->functions}, @{$interface->anonymousFunctions}) {
+        my $isLegacyCaller = grep { $_ eq "legacycaller" } @{$operation->specials};
+        if ($isLegacyCaller) {
+            $interface->{LegacyCallers} = [] if !exists $interface->{LegacyCallers};
+
+            my $clonedOperation = IDLParser::cloneOperation($operation);
+            push($interface->{LegacyCallers}, $clonedOperation);
+    
+            $clonedOperation->{overloads} = $interface->{LegacyCallers};
+            $clonedOperation->{overloadIndex} = @{$interface->{LegacyCallers}};
+        }
+    }
+}
+
 sub EventHandlerAttributeEventName
 {
     my $attribute = shift;
@@ -1740,8 +1757,6 @@ sub GenerateHeader
         }
     }
 
-    $headerIncludes{"<runtime/CallData.h>"} = 1 if $interface->extendedAttributes->{CustomCall};
-
     $headerIncludes{"$interfaceName.h"} = 1 if $hasParent && $interface->extendedAttributes->{JSGenerateToNativeObject};
 
     $headerIncludes{"SVGElement.h"} = 1 if $className =~ /^JSSVG/;
@@ -1864,7 +1879,6 @@ sub GenerateHeader
     }
     $structureFlags{"JSC::NewImpurePropertyFiresWatchpoints"} = 1 if $interface->extendedAttributes->{NewImpurePropertyFiresWatchpoints};
     $structureFlags{"JSC::IsImmutablePrototypeExoticObject"} = 1 if $interface->extendedAttributes->{IsImmutablePrototypeExoticObject};
-    $structureFlags{"JSC::TypeOfShouldCallGetCallData"} = 1 if $interface->extendedAttributes->{CustomCall};
 
     # Getters
     if ($hasGetter) {
@@ -1920,8 +1934,12 @@ sub GenerateHeader
     # Custom pushEventHandlerScope function
     push(@headerContent, "    JSC::JSScope* pushEventHandlerScope(JSC::ExecState*, JSC::JSScope*) const;\n\n") if $interface->extendedAttributes->{JSCustomPushEventHandlerScope};
 
-    # Custom call functions
-    push(@headerContent, "    static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&);\n\n") if $interface->extendedAttributes->{CustomCall};
+    # LegacyCaller and custom call functions
+    if (IsCallable($interface)) {
+        push(@headerContent, "    static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&);\n\n");
+        $headerIncludes{"<runtime/CallData.h>"} = 1;
+        $structureFlags{"JSC::TypeOfShouldCallGetCallData"} = 1;
+    }
 
     # Custom deleteProperty function
     push(@headerContent, "    static bool deleteProperty(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName);\n") if $interface->extendedAttributes->{CustomDeleteProperty};
@@ -2584,14 +2602,16 @@ sub getConditionalForFunctionConsideringOverloads
 # http://heycam.github.io/webidl/#es-overloads
 sub GenerateOverloadedFunctionOrConstructor
 {
-    my ($function, $interface, $isConstructor) = @_;
+    my ($function, $interface, $variant) = @_;
     my %allSets = ComputeEffectiveOverloadSet($function->{overloads});
 
     my $interfaceName = $interface->type->name;
     my $className = "JS$interfaceName";
     my $functionName;
-    if ($isConstructor) {
+    if ($variant eq "constructor") {
         $functionName = "construct${className}";
+    } elsif ($variant eq "legacycaller") {
+        $functionName = "call${className}";
     } else {
         my $kind = $function->isStatic ? "Constructor" : (OperationShouldBeOnInstance($interface, $function) ? "Instance" : "Prototype");
         $functionName = "js${interfaceName}${kind}Function" . $codeGenerator->WK_ucfirst($function->name);
@@ -2677,7 +2697,7 @@ sub GenerateOverloadedFunctionOrConstructor
     my $conditionalAttribute = getConditionalForFunctionConsideringOverloads($function);
     my $conditionalString = $conditionalAttribute ? $codeGenerator->GenerateConditionalStringFromAttributeValue($conditionalAttribute) : undef;
     push(@implContent, "#if ${conditionalString}\n") if $conditionalString;
-    if ($isConstructor) {
+    if ($variant eq "constructor") {
         push(@implContent, "template<> EncodedJSValue JSC_HOST_CALL ${className}Constructor::construct(ExecState* state)\n");
     } else {
         push(@implContent, "EncodedJSValue JSC_HOST_CALL ${functionName}(ExecState* state)\n");
@@ -4259,16 +4279,18 @@ END
             push(@implContent, "#endif\n\n") if $conditional;
 
             # Generate a function dispatching call to the rest of the overloads.
-            GenerateOverloadedFunctionOrConstructor($function, $interface, 0) if !$isCustom && $isOverloaded && $function->{overloadIndex} == @{$function->{overloads}};
+            GenerateOverloadedFunctionOrConstructor($function, $interface, "operation") if !$isCustom && $isOverloaded && $function->{overloadIndex} == @{$function->{overloads}};
         }
 
         push(@implContent, $endAppleCopyright) if $inAppleCopyright;
 
     }
 
+    GenerateLegacyCallerDefinitions($interface, $className);
 
     GenerateImplementationIterableFunctions($interface) if $interface->iterable;
     GenerateSerializerFunction($interface, $className) if $interface->serializable;
+
     AddToImplIncludes("JSDOMMapLike.h") if $interface->mapLike;
 
     if ($needsVisitChildren) {
@@ -4573,6 +4595,62 @@ sub GenerateSerializerFunction
     push(@implContent, "\n");
 }
 
+sub GenerateLegacyCallerDefinitions
+{
+    my ($interface, $className) = @_;
+
+    if (!IsCallable($interface) || $interface->extendedAttributes->{CustomCall}) {
+        return;
+    }
+
+    my @legacyCallers = @{$interface->{LegacyCallers}};
+    if (@legacyCallers > 1) {
+        foreach my $legacyCaller (@legacyCallers) {
+            GenerateLegacyCallerDefinition($interface, $className, $legacyCaller);
+        }
+        GenerateOverloadedFunctionOrConstructor($legacyCallers[0], $interface, "legacycaller");
+    } else {
+        GenerateLegacyCallerDefinition($interface, $className, $legacyCallers[0]);
+    }
+
+    push(@implContent, "CallType ${className}::getCallData(JSCell*, CallData& callData)\n");
+    push(@implContent, "{\n");
+    push(@implContent, "    callData.native.function = call${className};\n");
+    push(@implContent, "    return CallType::Host;\n");
+    push(@implContent, "}\n");
+    push(@implContent, "\n");
+}
+
+sub GenerateLegacyCallerDefinition
+{
+    my ($interface, $className, $function) = @_;
+
+    my $isOverloaded = $function->{overloads} && @{$function->{overloads}} > 1;
+    if ($isOverloaded) {
+        push(@implContent, "static inline EncodedJSValue call${className}$function->{overloadIndex}(ExecState* state)\n");
+    } else {
+        push(@implContent, "static EncodedJSValue JSC_HOST_CALL call${className}(ExecState* state)\n");
+    }
+
+    push(@implContent, "{\n");
+    push(@implContent, "    VM& vm = state->vm();\n");
+    push(@implContent, "    auto throwScope = DECLARE_THROW_SCOPE(vm);\n");
+    push(@implContent, "    UNUSED_PARAM(throwScope);\n");
+
+    GenerateArgumentsCountCheck(\@implContent, $function, $interface);
+
+    push(@implContent, "    auto* castedThis = jsCast<${className}*>(state->jsCallee());\n");
+    push(@implContent, "    ASSERT(castedThis);\n");
+    push(@implContent, "    auto& impl = castedThis->wrapped();\n");
+
+    my $functionImplementationName = $function->extendedAttributes->{ImplementedAs} || $codeGenerator->WK_lcfirst($function->name) || "legacyCallerOperationFromBindings";
+    my $functionString = GenerateParametersCheck(\@implContent, $function, $interface, $functionImplementationName);
+
+    GenerateImplementationFunctionCall($function, $functionString, "    ", $interface);
+
+    push(@implContent, "}\n\n");
+}
+
 sub GenerateCallWithUsingReferences
 {
     my ($callWith, $outputArray, $returnValue, $function) = @_;
@@ -5193,7 +5271,8 @@ sub GenerateCallbackImplementationContent
 
         GenerateConstructorDefinitions($contentRef, $className, "", $visibleName, $interfaceOrCallback);
 
-        push(@$contentRef, "JSValue ${className}::getConstructor(VM& vm, const JSGlobalObject* globalObject)\n{\n");
+        push(@$contentRef, "JSValue ${className}::getConstructor(VM& vm, const JSGlobalObject* globalObject)\n");
+        push(@$contentRef, "{\n");
         push(@$contentRef, "    return getDOMConstructor<${className}Constructor>(vm, *jsCast<const JSDOMGlobalObject*>(globalObject));\n");
         push(@$contentRef, "}\n\n");
     }
@@ -5257,7 +5336,7 @@ sub GenerateCallbackImplementationContent
     push(@$contentRef, "}\n\n");
 }
 
-sub GenerateImplementationFunctionCall()
+sub GenerateImplementationFunctionCall
 {
     my ($function, $functionString, $indent, $interface) = @_;
 
@@ -6178,7 +6257,7 @@ sub GenerateConstructorDefinitions
             foreach my $constructor (@constructors) {
                 GenerateConstructorDefinition($outputArray, $className, $protoClassName, $visibleInterfaceName, $interface, $generatingNamedConstructor, $constructor);
             }
-            GenerateOverloadedFunctionOrConstructor(@{$interface->constructors}[0], $interface, 1);
+            GenerateOverloadedFunctionOrConstructor(@{$interface->constructors}[0], $interface, "constructor");
         } elsif (@constructors == 1) {
             GenerateConstructorDefinition($outputArray, $className, $protoClassName, $visibleInterfaceName, $interface, $generatingNamedConstructor, $constructors[0]);
         } else {
@@ -6376,6 +6455,12 @@ sub IsConstructable
         || $interface->extendedAttributes->{JSBuiltinConstructor};
 }
 
+sub IsCallable
+{
+    my $interface = shift;
+    return $interface->extendedAttributes->{CustomCall} || $interface->{LegacyCallers}
+}
+
 sub HeaderNeedsPrototypeDeclaration
 {
     my $interface = shift;
index cad158c..95ee3f2 100644 (file)
@@ -80,7 +80,7 @@ struct( IDLArgument => {
     isVariadic => '$',
     isOptional => '$',
     default => '$',
-    extendedAttributes => '$',
+    extendedAttributes => '%',
 });
 
 # https://heycam.github.io/webidl/#idl-operations
@@ -93,7 +93,7 @@ struct( IDLOperation => {
     isSerializer => '$',
     isMapLike => '$',
     specials => '@',
-    extendedAttributes => '$',
+    extendedAttributes => '%',
 });
 
 
@@ -513,7 +513,6 @@ sub makeSimpleType
 
 sub cloneType
 {
-    my $self = shift;
     my $type = shift;
 
     my $clonedType = IDLType->new();
@@ -524,12 +523,50 @@ sub cloneType
     copyExtendedAttributes($clonedType->extendedAttributes, $type->extendedAttributes);
 
     foreach my $subtype (@{$type->subtypes}) {
-        push(@{$clonedType->subtypes}, $self->cloneType($subtype));
+        push(@{$clonedType->subtypes}, cloneType($subtype));
     }
 
     return $clonedType;
 }
 
+sub cloneArgument
+{
+    my $argument = shift;
+
+    my $clonedArgument = IDLArgument->new();
+    $clonedArgument->name($argument->name);
+    $clonedArgument->type(cloneType($argument->type));
+    $clonedArgument->isVariadic($argument->isVariadic);
+    $clonedArgument->isOptional($argument->isOptional);
+    $clonedArgument->default($argument->default);
+    copyExtendedAttributes($clonedArgument->extendedAttributes, $argument->extendedAttributes);
+
+    return $clonedArgument;
+}
+
+sub cloneOperation
+{
+    my $operation = shift;
+
+    my $clonedOperation = IDLOperation->new();
+    $clonedOperation->name($operation->name);
+    $clonedOperation->type(cloneType($operation->type));
+    
+    foreach my $argument (@{$operation->arguments}) {
+        push(@{$clonedOperation->arguments}, cloneArgument($argument));
+    }
+
+    $clonedOperation->isStatic($operation->isStatic);
+    $clonedOperation->isIterable($operation->isIterable);
+    $clonedOperation->isSerializer($operation->isSerializer);
+    $clonedOperation->isMapLike($operation->isMapLike);
+    $clonedOperation->specials($operation->specials);
+
+    copyExtendedAttributes($clonedOperation->extendedAttributes, $operation->extendedAttributes);
+
+    return $clonedOperation;
+}
+
 my $nextAttribute_1 = '^(attribute|inherit)$';
 my $nextPrimitiveType_1 = '^(int|long|short|unsigned)$';
 my $nextPrimitiveType_2 = '^(double|float|unrestricted)$';
@@ -645,7 +682,7 @@ sub typeByApplyingTypedefs
     if (exists $typedefs{$type->name}) {
         my $typedef = $typedefs{$type->name};
 
-        my $clonedType = $self->cloneType($typedef->type);
+        my $clonedType = cloneType($typedef->type);
         $clonedType->isNullable($clonedType->isNullable || $type->isNullable);
         $self->moveExtendedAttributesApplicableToTypes($clonedType, $type->extendedAttributes);
 
index 3f92dc3..bbcf37b 100644 (file)
@@ -1260,6 +1260,7 @@ JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionSingleConditionalOve
 JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionAttachShadowRoot(JSC::ExecState*);
 JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionOperationWithExternalDictionaryParameter(JSC::ExecState*);
 JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionBufferSourceParameter(JSC::ExecState*);
+JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionLegacyCallerNamed(JSC::ExecState*);
 JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionToString(JSC::ExecState*);
 JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionToJSON(JSC::ExecState*);
 
@@ -1922,6 +1923,7 @@ static const HashTableValue JSTestObjPrototypeTableValues[] =
     { "attachShadowRoot", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionAttachShadowRoot), (intptr_t) (1) } },
     { "operationWithExternalDictionaryParameter", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionOperationWithExternalDictionaryParameter), (intptr_t) (1) } },
     { "bufferSourceParameter", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionBufferSourceParameter), (intptr_t) (1) } },
+    { "legacyCallerNamed", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionLegacyCallerNamed), (intptr_t) (1) } },
     { "toString", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionToString), (intptr_t) (0) } },
     { "toJSON", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionToJSON), (intptr_t) (0) } },
 #if ENABLE(Condition1)
@@ -8763,6 +8765,26 @@ static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionBufferSourceParamete
     return JSValue::encode(jsUndefined());
 }
 
+static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionLegacyCallerNamedCaller(JSC::ExecState*, JSTestObj*, JSC::ThrowScope&);
+
+EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionLegacyCallerNamed(ExecState* state)
+{
+    return BindingCaller<JSTestObj>::callOperation<jsTestObjPrototypeFunctionLegacyCallerNamedCaller>(state, "legacyCallerNamed");
+}
+
+static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionLegacyCallerNamedCaller(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 param = convert<IDLLong>(*state, state->uncheckedArgument(0));
+    RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
+    impl.legacyCallerNamed(WTFMove(param));
+    return JSValue::encode(jsUndefined());
+}
+
 static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionToStringCaller(JSC::ExecState*, JSTestObj*, JSC::ThrowScope&);
 
 EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionToString(ExecState* state)
@@ -8778,6 +8800,73 @@ static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionToStringCaller(JSC::
     return JSValue::encode(toJS<IDLUSVString>(*state, impl.stringifierAttribute()));
 }
 
+static inline EncodedJSValue callJSTestObj1(ExecState* state)
+{
+    VM& vm = state->vm();
+    auto throwScope = DECLARE_THROW_SCOPE(vm);
+    UNUSED_PARAM(throwScope);
+    if (UNLIKELY(state->argumentCount() < 1))
+        return throwVMError(state, throwScope, createNotEnoughArgumentsError(state));
+    auto* castedThis = jsCast<JSTestObj*>(state->jsCallee());
+    ASSERT(castedThis);
+    auto& impl = castedThis->wrapped();
+    auto param = convert<IDLLong>(*state, state->uncheckedArgument(0));
+    RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
+    impl.legacyCallerNamed(WTFMove(param));
+    return JSValue::encode(jsUndefined());
+}
+
+static inline EncodedJSValue callJSTestObj2(ExecState* state)
+{
+    VM& vm = state->vm();
+    auto throwScope = DECLARE_THROW_SCOPE(vm);
+    UNUSED_PARAM(throwScope);
+    if (UNLIKELY(state->argumentCount() < 1))
+        return throwVMError(state, throwScope, createNotEnoughArgumentsError(state));
+    auto* castedThis = jsCast<JSTestObj*>(state->jsCallee());
+    ASSERT(castedThis);
+    auto& impl = castedThis->wrapped();
+    auto param = convert<IDLDOMString>(*state, state->uncheckedArgument(0));
+    RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
+    return JSValue::encode(toJS<IDLLong>(impl.legacyCallerOperationFromBindings(WTFMove(param))));
+}
+
+static inline EncodedJSValue callJSTestObj3(ExecState* state)
+{
+    VM& vm = state->vm();
+    auto throwScope = DECLARE_THROW_SCOPE(vm);
+    UNUSED_PARAM(throwScope);
+    auto* castedThis = jsCast<JSTestObj*>(state->jsCallee());
+    ASSERT(castedThis);
+    auto& impl = castedThis->wrapped();
+    impl.legacyCallerOperationFromBindings();
+    return JSValue::encode(jsUndefined());
+}
+
+EncodedJSValue JSC_HOST_CALL callJSTestObj(ExecState* state)
+{
+    VM& vm = state->vm();
+    auto throwScope = DECLARE_THROW_SCOPE(vm);
+    UNUSED_PARAM(throwScope);
+    size_t argsCount = std::min<size_t>(1, state->argumentCount());
+    if (argsCount == 0) {
+        return callJSTestObj3(state);
+    }
+    if (argsCount == 1) {
+        JSValue distinguishingArg = state->uncheckedArgument(0);
+        if (distinguishingArg.isNumber())
+            return callJSTestObj1(state);
+        return callJSTestObj2(state);
+    }
+    return throwVMTypeError(state, throwScope);
+}
+
+CallType JSTestObj::getCallData(JSCell*, CallData& callData)
+{
+    callData.native.function = callJSTestObj;
+    return CallType::Host;
+}
+
 JSC::JSObject* JSTestObj::serialize(ExecState* state, JSTestObj* thisObject, ThrowScope& throwScope)
 {
     auto& vm = state->vm();
index c8e067e..8fc59d3 100644 (file)
@@ -23,6 +23,7 @@
 #include "JSDOMConvert.h"
 #include "JSDOMWrapper.h"
 #include "TestObj.h"
+#include <runtime/CallData.h>
 #include <wtf/NeverDestroyed.h>
 
 namespace WebCore {
@@ -51,6 +52,8 @@ public:
         return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());
     }
 
+    static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&);
+
     static void getOwnPropertyNames(JSC::JSObject*, JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode = JSC::EnumerationMode());
     static JSC::JSValue getConstructor(JSC::VM&, const JSC::JSGlobalObject*);
     static JSC::JSObject* serialize(JSC::ExecState*, JSTestObj* thisObject, JSC::ThrowScope&);
@@ -69,7 +72,7 @@ public:
     static JSC::JSValue classMethod2(JSC::ExecState&);
     JSC::JSValue testCustomPromiseFunction(JSC::ExecState&);
 public:
-    static const unsigned StructureFlags = JSC::HasStaticPropertyTable | JSC::InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | JSC::OverridesGetOwnPropertySlot | JSC::OverridesGetPropertyNames | Base::StructureFlags;
+    static const unsigned StructureFlags = JSC::HasStaticPropertyTable | JSC::InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | JSC::OverridesGetOwnPropertySlot | JSC::OverridesGetPropertyNames | JSC::TypeOfShouldCallGetCallData | Base::StructureFlags;
 protected:
     JSTestObj(JSC::Structure*, JSDOMGlobalObject&, Ref<TestObj>&&);
 
index eace733..f04b241 100644 (file)
@@ -433,6 +433,10 @@ enum TestConfidence { "high", "kinda-low" };
     serializer = {create, readOnlyStringAttr, enumAttr, longAttr};
 
     void bufferSourceParameter(BufferSource data);
+    
+    legacycaller void legacyCallerNamed(long param);
+    legacycaller long (DOMString param);
+    legacycaller void ();
 };
 
 // The following comment should not generate any code.
index 64a98ce..1fdd203 100644 (file)
@@ -4979,6 +4979,11 @@ Ref<HTMLCollection> Document::all()
     return ensureRareData().ensureNodeLists().addCachedCollection<HTMLAllCollection>(*this, DocAll);
 }
 
+Ref<HTMLCollection> Document::allFilteredByName(const AtomicString& name)
+{
+    return ensureRareData().ensureNodeLists().addCachedCollection<HTMLAllNamedSubCollection>(*this, DocumentAllNamedItems, name);
+}
+
 Ref<HTMLCollection> Document::windowNamedItems(const AtomicString& name)
 {
     return ensureRareData().ensureNodeLists().addCachedCollection<WindowNameCollection>(*this, WindowNamedItems, name);
index 44ba181..994a9a5 100644 (file)
@@ -464,9 +464,10 @@ public:
     WEBCORE_EXPORT Ref<HTMLCollection> anchors();
     WEBCORE_EXPORT Ref<HTMLCollection> scripts();
     Ref<HTMLCollection> all();
+    Ref<HTMLCollection> allFilteredByName(const AtomicString&);
 
-    Ref<HTMLCollection> windowNamedItems(const AtomicString& name);
-    Ref<HTMLCollection> documentNamedItems(const AtomicString& name);
+    Ref<HTMLCollection> windowNamedItems(const AtomicString&);
+    Ref<HTMLCollection> documentNamedItems(const AtomicString&);
 
     // Other methods (not part of DOM)
     bool isSynthesized() const { return m_isSynthesized; }
index 00bb263..900e5a8 100644 (file)
@@ -97,15 +97,22 @@ bool CachedHTMLCollection<HTMLCollectionClass, traversalType>::elementMatches(El
 
 static inline bool nameShouldBeVisibleInDocumentAll(HTMLElement& element)
 {
-    // The document.all collection returns only certain types of elements by name,
-    // although it returns any type of element by id.
-    return element.hasTagName(HTMLNames::appletTag)
+    // https://html.spec.whatwg.org/multipage/infrastructure.html#all-named-elements
+    return element.hasTagName(HTMLNames::aTag)
+        || element.hasTagName(HTMLNames::appletTag)
+        || element.hasTagName(HTMLNames::buttonTag)
         || element.hasTagName(HTMLNames::embedTag)
         || element.hasTagName(HTMLNames::formTag)
+        || element.hasTagName(HTMLNames::frameTag)
+        || element.hasTagName(HTMLNames::framesetTag)
+        || element.hasTagName(HTMLNames::iframeTag)
         || element.hasTagName(HTMLNames::imgTag)
         || element.hasTagName(HTMLNames::inputTag)
+        || element.hasTagName(HTMLNames::mapTag)
+        || element.hasTagName(HTMLNames::metaTag)
         || element.hasTagName(HTMLNames::objectTag)
-        || element.hasTagName(HTMLNames::selectTag);
+        || element.hasTagName(HTMLNames::selectTag)
+        || element.hasTagName(HTMLNames::textareaTag);
 }
 
 static inline bool nameShouldBeVisibleInDocumentAll(Element& element)
index fdd7f3e..d09276a 100644 (file)
@@ -39,6 +39,8 @@ enum CollectionType {
     WindowNamedItems,
     DocumentNamedItems,
 
+    DocumentAllNamedItems, // Sub-collection returned by the "all" collection when there are multiple items with the same name
+
     // Unnamed HTMLCollection types cached in elements.
     NodeChildren, // first-level children (IE)
     TableTBodies, // all <tbody> elements in this table
index 83052ec..9bbed3b 100644 (file)
@@ -77,6 +77,7 @@ bool GenericCachedHTMLCollection<traversalType>::elementMatches(Element& element
     case ByHTMLTag:
     case AllDescendants:
     case DocAll:
+    case DocumentAllNamedItems:
     case DocumentNamedItems:
     case FormControls:
     case SelectOptions:
index eaef792..358ceb0 100644 (file)
@@ -27,6 +27,8 @@
 #include "HTMLAllCollection.h"
 
 #include "Element.h"
+#include "NodeRareData.h"
+#include <runtime/Identifier.h>
 
 namespace WebCore {
 
@@ -40,23 +42,50 @@ inline HTMLAllCollection::HTMLAllCollection(Document& document, CollectionType t
 {
 }
 
-Element* HTMLAllCollection::namedItemWithIndex(const AtomicString& name, unsigned index) const
+// https://html.spec.whatwg.org/multipage/infrastructure.html#dom-htmlallcollection-item
+std::optional<Variant<RefPtr<HTMLCollection>, RefPtr<Element>>> HTMLAllCollection::namedOrIndexedItemOrItems(const AtomicString& nameOrIndex) const
 {
-    updateNamedElementCache();
-    const CollectionNamedElementCache& cache = namedItemCaches();
+    if (nameOrIndex.isNull())
+        return std::nullopt;
 
-    if (const Vector<Element*>* elements = cache.findElementsWithId(name)) {
-        if (index < elements->size())
-            return elements->at(index);
-        index -= elements->size();
-    }
+    if (auto index = JSC::parseIndex(*nameOrIndex.impl()))
+        return Variant<RefPtr<HTMLCollection>, RefPtr<Element>> { RefPtr<Element> { item(index.value()) } };
 
-    if (const Vector<Element*>* elements = cache.findElementsWithName(name)) {
-        if (index < elements->size())
-            return elements->at(index);
-    }
+    return namedItemOrItems(nameOrIndex);
+}
+
+// https://html.spec.whatwg.org/multipage/infrastructure.html#concept-get-all-named
+std::optional<Variant<RefPtr<HTMLCollection>, RefPtr<Element>>> HTMLAllCollection::namedItemOrItems(const AtomicString& name) const
+{
+    auto namedItems = this->namedItems(name);
+
+    if (namedItems.isEmpty())
+        return std::nullopt;
+    if (namedItems.size() == 1)
+        return Variant<RefPtr<HTMLCollection>, RefPtr<Element>> { RefPtr<Element> { WTFMove(namedItems[0]) } };
+
+    return Variant<RefPtr<HTMLCollection>, RefPtr<Element>> { RefPtr<HTMLCollection> { downcast<Document>(ownerNode()).allFilteredByName(name) } };
+}
+
+HTMLAllNamedSubCollection::~HTMLAllNamedSubCollection()
+{
+    ownerNode().nodeLists()->removeCachedCollection(this, m_name);
+}
+
+bool HTMLAllNamedSubCollection::elementMatches(Element& element) const
+{
+    const auto& id = element.getIdAttribute();
+    if (id == m_name)
+        return true;
+
+    if (!nameShouldBeVisibleInDocumentAll(element))
+        return false;
+
+    const auto& name = element.getNameAttribute();
+    if (name == m_name)
+        return true;
 
-    return nullptr;
+    return false;
 }
 
 } // namespace WebCore
index 2539e91..98a6f8f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2009, 2011, 2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -26,6 +26,8 @@
 #pragma once
 
 #include "AllDescendantsCollection.h"
+#include <wtf/Optional.h>
+#include <wtf/Variant.h>
 
 namespace WebCore {
 
@@ -33,12 +35,35 @@ class HTMLAllCollection final : public AllDescendantsCollection {
 public:
     static Ref<HTMLAllCollection> create(Document&, CollectionType);
 
-    Element* namedItemWithIndex(const AtomicString& name, unsigned index) const;
+    std::optional<Variant<RefPtr<HTMLCollection>, RefPtr<Element>>> namedOrIndexedItemOrItems(const AtomicString& nameOrIndex) const;
+    std::optional<Variant<RefPtr<HTMLCollection>, RefPtr<Element>>> namedItemOrItems(const AtomicString&) const;
 
 private:
     HTMLAllCollection(Document&, CollectionType);
 };
 
+class HTMLAllNamedSubCollection final : public CachedHTMLCollection<HTMLAllNamedSubCollection, CollectionTraversalType::Descendants> {
+public:
+    static Ref<HTMLAllNamedSubCollection> create(Document& document, CollectionType type, const AtomicString& name)
+    {
+        return adoptRef(*new HTMLAllNamedSubCollection(document, type, name));
+    }
+    virtual ~HTMLAllNamedSubCollection();
+
+    bool elementMatches(Element&) const;
+
+private:
+    HTMLAllNamedSubCollection(Document& document, CollectionType type, const AtomicString& name)
+        : CachedHTMLCollection<HTMLAllNamedSubCollection, CollectionTraversalType::Descendants>(document, type)
+        , m_name(name)
+    {
+        ASSERT(type == DocumentAllNamedItems);
+    }
+
+    AtomicString m_name;
+};
+
 } // namespace WebCore
 
 SPECIALIZE_TYPE_TRAITS_HTMLCOLLECTION(HTMLAllCollection, DocAll)
+SPECIALIZE_TYPE_TRAITS_HTMLCOLLECTION(HTMLAllNamedSubCollection, DocumentAllNamedItems)
index 67f4c93..8fcb68c 100644 (file)
  */
 
 [
-    CustomCall,
-    CustomNamedGetter,
     LegacyUnenumerableNamedProperties,
     MasqueradesAsUndefined,
     GenerateIsReachable=ImplOwnerNodeRoot,
 ] interface HTMLAllCollection {
     readonly attribute unsigned long length;
 
-    [Custom] getter Element? item(unsigned long index);
-    [Custom] getter (HTMLCollection or Element)? namedItem(DOMString name);
-    // [Custom] legacycaller (HTMLCollection or Element)? item(optional DOMString nameOrIndex);
+    getter Element? (unsigned long index);
+    [ImplementedAs=namedItemOrItems] getter (HTMLCollection or Element)? namedItem(DOMString name);
+    [ImplementedAs=namedOrIndexedItemOrItems] legacycaller (HTMLCollection or Element)? item(optional DOMString nameOrIndex);
 };
-
index efa53e3..a0349b8 100644 (file)
@@ -44,6 +44,7 @@ inline auto HTMLCollection::rootTypeFromCollectionType(CollectionType type) -> R
     case DocAll:
     case WindowNamedItems:
     case DocumentNamedItems:
+    case DocumentAllNamedItems:
     case FormControls:
         return HTMLCollection::IsRootedAtDocument;
     case AllDescendants:
@@ -96,8 +97,8 @@ static NodeListInvalidationType invalidationTypeExcludingIdAndNameAttributes(Col
     case DocLinks:
         return InvalidateOnHRefAttrChange;
     case WindowNamedItems:
-        return InvalidateOnIdNameAttrChange;
     case DocumentNamedItems:
+    case DocumentAllNamedItems:
         return InvalidateOnIdNameAttrChange;
     case FormControls:
         return InvalidateForFormControls;
@@ -130,6 +131,7 @@ HTMLCollection::~HTMLCollection()
     case ByHTMLTag:
     case WindowNamedItems:
     case DocumentNamedItems:
+    case DocumentAllNamedItems:
         break;
     default:
         ownerNode().nodeLists()->removeCachedCollection(this);