NodeFilter should be a callback interface
https://bugs.webkit.org/show_bug.cgi?id=148415

Reviewed by Geoffrey Garen.

Source/WebCore:

NodeFilter is now a callback interface, instead of a regular interface,
as per the DOM specification:
https://dom.spec.whatwg.org/#interface-nodefilter

One major difference is that TreeWalker.filter / NodeIterator is
supposed to be a Function / Object (passed by JavaScript), but it was a
JSNodeFilter wrapper in WebKit. Also, window.NodeFilter is not supposed
to have a prototype property.

This behavior is consistent with Firefox. However, Chrome still has its
own NodeFilter wrapper.

Tests:
http/tests/w3c/dom/traversal/NodeIterator-expected.html (rebaselined)
http/tests/w3c/dom/traversal/TreeWalker.html (rebaselined)

* CMakeLists.txt:
* WebCore.vcxproj/WebCore.vcxproj:
* WebCore.vcxproj/WebCore.vcxproj.filters:
* WebCore.xcodeproj/project.pbxproj:
Add / Remove files to the project files.

* dom/NodeFilterCondition.cpp:
(WebCore::NodeFilterCondition::acceptNode):
* dom/NodeFilterCondition.h:
* bindings/gobject/GObjectNodeFilterCondition.cpp:
(WebCore::GObjectNodeFilterCondition::acceptNode):
* bindings/gobject/GObjectNodeFilterCondition.h:
* bindings/objc/ObjCNodeFilterCondition.h:
* bindings/objc/ObjCNodeFilterCondition.mm:
(WebCore::ObjCNodeFilterCondition::acceptNode):
Drop ExecState parameter as it is not used.

* bindings/gobject/WebKitDOMNodeFilter.cpp:
(WebKit::core):
Use NativeNodeFilter type instead of NodeFilter. NodeFilter is now
a pure interface with 2 subclasses: NativeNodeFilter for the native
bindings and JSNodeFilter for the JS bindings.

* bindings/js/JSBindingsAllInOne.cpp:
Drop JSNodeFilterCondition.cpp as it was removed.

* bindings/js/JSCallbackData.cpp:
(WebCore::JSCallbackData::invokeCallback):
Throw a TypeError if the callback object being invoked is not callable
and does not have a callable property with the expected name. There
are several layout tests covering this (including w3c ones). Previously,
NodeFilter was not using the generic JSCallbackData and the exception
throwing was in JSNodeFilterCondition::acceptNode() instead.

* bindings/js/JSNodeFilterCondition.cpp: Removed.
* bindings/js/JSNodeFilterCondition.h: Removed.
Drop this class. JSNodeFilter / JSNodeFilterCustom now basically take
care of all this.

* bindings/js/JSNodeFilterCustom.cpp:
(WebCore::JSNodeFilter::acceptNode):
Complete rewrite. This file is now only used to provide a custom
implementation for JSNodeFilter::acceptNode(). The code is similar to
what was previously done in JSNodeFilterCondition::acceptNode().
There are several reasons we need custom bindings here:
- The bindings generator does not handle yet callback functions
  returning anything else than a boolean.
- The specification clearly states that we need to rethrow exceptions
  thrown by the callback function. However, the default behavior of
  our bindings is to simply report the exception.

* bindings/scripts/CodeGeneratorGObject.pm:
Only skip functions that have parameters that are callback *functions*,
not callback *interfaces*. Callback interfaces are very similar to
interfaces and the generator is able to handle them. This change was
needed for the GTK bindings generator would no longer generate bindings
for Document.createNodeIterator() / Document.createTreeWalker(), now
that NodeFilter is a callback interface instead of a regular interface.

* bindings/scripts/CodeGeneratorJS.pm:
(GenerateCallbackHeader):
(GenerateCallbackImplementation):
Generate a toJS() function for callback interfaces as well. Previously,
we would only generate those for regular interfaces. This is needed
because NodeFilter is now a callback interface and it is exposed to
JS via NodeIterator.filter / TreeWalker.filter. The implementation
merely returns the callback object / function inside the JSCalbackData
so the JS gets back the object / function it passed in.

* bindings/scripts/CodeGeneratorObjC.pm:
Tweak the ObjC bindings generator to use NativeNodeFilter class instead
of NodeFilter as NodeFilter is now a pure interfaces. Native bindings
are now expected to use the NativeNodeFilter subclass instead.

* bindings/scripts/test/JS/JSTestCallback.cpp:
* bindings/scripts/test/JS/JSTestCallback.h:
* bindings/scripts/test/JS/JSTestCallbackFunction.cpp:
* bindings/scripts/test/JS/JSTestCallbackFunction.h:
Rebaseline bindings tests now that we generate toJS() functions for
callback functions / interfaces.

* dom/DOMAllInOne.cpp:
Drop NodeFilter.cpp as it was removed.

* dom/NativeNodeFilter.cpp: Added.
* dom/NativeNodeFilter.h: Added.
Introduce new NativeNodeFilter class which subclasses the NodeFilter
interface and is used by native bindings. Its accept() implementation
uses NodeFilterCondition object internally to filter the nodes instead
of a JS callback.

* dom/NodeFilter.cpp: Removed.
* dom/NodeFilter.h:
Make NodeFilter a pure interface. Its previous code is now either in
NativeNodeFilter of JSNodeFilter.

* dom/NodeFilter.idl:
Make NodeFilter a callback interface instead of a regular interface,
as per the DOM specification. Also have its accept() operation return
an unsigned short instead of a short to match the specification.
The ObjC version still returns a short though for backward
compatibility.

* dom/NodeFilterCondition.cpp:
(WebCore::NodeFilterCondition::acceptNode):
* dom/NodeFilterCondition.h:

* dom/NodeIterator.cpp:
* dom/NodeIterator.h:
* dom/NodeIterator.idl:
* dom/Traversal.cpp:
* dom/Traversal.h:
* dom/TreeWalker.cpp:
* dom/TreeWalker.h:
* dom/TreeWalker.idl:
Stop passing ExecState to TreeWalker / NodeIterator functions. It no
longer seems to be needed as we now use the JSCallbackData abstraction
for invoking JS.

LayoutTests:

* fast/dom/TreeWalker/acceptNode-filter-expected.txt:
Rebaseline, the new exception message is different but the exception
type is the same.

* fast/dom/constants-expected.txt:
* fast/dom/constants.html:
Stop checking for constants on NodeFilter instances as those are now
Functions (implemented by the JavaScript). Those constants are on
window.NodeFilter still. I verified that this is consistant with
Firefox.

* fast/dom/global-constructors.html:
Update the check to verify that the prototype of a NodeFilter instance
is the Function prototype, not the NodeFilter prototype. NodeFilter
should not have a prototype as it is a callback interface.

* fast/dom/node-filter-gc.html:
Pass null for the filter argument instead of 0. The functions expect
a nullable NodeFilter object. Passing 0 here throws.

* fast/dom/node-filter-interface-expected.txt:
Rebaseline. window.NodeFilter no longer has a prototype. This is because
callback interfaces are not supposed to have a prototype property, as
per the Web IDL specification:
https://heycam.github.io/webidl/#interface-prototype-object

I also verified that this is consistent with Firefox.

* http/tests/w3c/dom/interfaces-expected.txt:
* http/tests/w3c/dom/nodes/Document-createTreeWalker-expected.txt:
* http/tests/w3c/dom/traversal/NodeIterator-expected.txt:
* http/tests/w3c/dom/traversal/TreeWalker-expected.txt:
Rebaseline W3C tests. We are now passing a lot of checks because they
check that TreeWalker.filter / NodeIterator.filter is a Function.

* traversal/size-zero-run.html:
Fix the test to pass a null node filter instead of NodeFilter.FILTER_ACCEPT.
The call was not valid and now correctly throws. The JS is supposed to pass
in a nullable NodeFilter, not a constant. I think the code meant to say
"function() { return NodeFilter.FILTER_ACCEPT; }", however, I used null as
it is shorter and equivalent.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@189230 268f45cc-cd09-0410-ab3c-d52691b4dbfc
52 files changed