[WebIDL] Generate named property deleters
authorweinig@apple.com <weinig@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 30 May 2017 23:54:51 +0000 (23:54 +0000)
committerweinig@apple.com <weinig@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 30 May 2017 23:54:51 +0000 (23:54 +0000)
https://bugs.webkit.org/show_bug.cgi?id=172688

Reviewed by Chris Dumez.

Source/WebCore:

Test: js/dom/named-property-deleter.html

* WebCore.xcodeproj/project.pbxproj:
Add new file, JSDOMAbstractOperations.h

* bindings/js/JSDOMAbstractOperations.h: Added.
(WebCore::isVisibleNamedProperty):
Add an implementation of the abstract operation WebIDL calls the 'named property visibility algorithm'.
It is used by many WebIDL algorithms, but currently I am only using this implementation for deleters.
In the future, we should try and move the other property access generators to use it as well.

* bindings/js/JSDOMStringMapCustom.cpp:
(WebCore::JSDOMStringMap::deleteProperty): Deleted.
(WebCore::JSDOMStringMap::deletePropertyByIndex): Deleted.
* bindings/js/JSStorageCustom.cpp:
(WebCore::JSStorage::deleteProperty): Deleted.
(WebCore::JSStorage::deletePropertyByIndex): Deleted.
Remove now generated deleteProperty and deletePropertyByIndex implementations.

* bindings/scripts/CodeGeneratorJS.pm:
(GenerateDeletePropertyCommon):
(GenerateDeletePropertyDefinition):
(GenerateDeletePropertyByIndexDefinition):
(GenerateNamedDeleterDefinition):
Added generation for named deleters. We generate both deleteProperty and deletePropertyByIndex.

(InstanceOverridesDelete):
Add predicate for whether the header should declare deleteProperty and deletePropertyByIndex.

(GenerateHeader):
Move property access hook declarations closer to each other. Use new InstanceOverridesDelete
predicate for deleteProperty and deletePropertyByIndex.

(GenerateImplementation):
Add call to generate named deleter if one exists.

(GenerateConstructorHelperMethods):
Remove an old FIXME that that was no longer true, there are no more interfaces that inherit from
an interface with [NoInterfaceObject].

* dom/DOMStringMap.idl:
Removes CustomDeleteProperty and sorts extended attributes.

* dom/DatasetDOMStringMap.h:
* dom/DatasetDOMStringMap.cpp:
(WebCore::DatasetDOMStringMap::isSupportedPropertyName):
Added. This is a bindings support function (much like supportedPropertyNames()) that is
used JSDOMAbstractOperations.h's isVisibleNamedProperty.

(WebCore::DatasetDOMStringMap::supportedPropertyNames):
Convert to an early return.

(WebCore::DatasetDOMStringMap::deleteNamedProperty):
(WebCore::DatasetDOMStringMap::deleteItem): Deleted.
Renamed deleteItem to deleteNamedProperty, which is the name the bindings use for deleter
operations without an identifier.

* page/DOMWindow.cpp:
(WebCore::DOMWindow::sessionStorage):
Fix incorrect indentation that bothered me.

* storage/Storage.cpp:
* storage/Storage.h:
- Remove isDisabledByPrivateBrowsing(), which had no definition.
- Add isSupportedPropertyName(), which the deleter code (via the isVisibleNamedProperty algorithm)
  needs.

* storage/Storage.idl:
Removes CustomDeleteProperty, sorts the extended attributes, adds 'deleter' special
to the removeItem operation and adds a commented out 'setter' special to the 'setItem'
operation.

* bindings/scripts/test/JS/JSTestObj.h:
Update result for declarations moving around.

* bindings/scripts/test/JS/JSTestNamedDeleterNoIdentifier.cpp: Added.
* bindings/scripts/test/JS/JSTestNamedDeleterNoIdentifier.h: Added.
* bindings/scripts/test/JS/JSTestNamedDeleterThrowingException.cpp: Added.
* bindings/scripts/test/JS/JSTestNamedDeleterThrowingException.h: Added.
* bindings/scripts/test/JS/JSTestNamedDeleterWithIdentifier.cpp: Added.
* bindings/scripts/test/JS/JSTestNamedDeleterWithIdentifier.h: Added.
* bindings/scripts/test/JS/JSTestNamedDeleterWithIndexedGetter.cpp: Added.
* bindings/scripts/test/JS/JSTestNamedDeleterWithIndexedGetter.h: Added.
* bindings/scripts/test/TestNamedDeleterNoIdentifier.idl: Added.
* bindings/scripts/test/TestNamedDeleterThrowingException.idl: Added.
* bindings/scripts/test/TestNamedDeleterWithIdentifier.idl: Added.
* bindings/scripts/test/TestNamedDeleterWithIndexedGetter.idl: Added.
Add new tests for named deleters.

LayoutTests:

* js/dom/named-property-deleter-expected.txt: Added.
* js/dom/named-property-deleter.html: Added.
Add test for various named deleter conditions.

* storage/domstorage/localstorage/delete-defineproperty-removal-expected.txt:
* storage/domstorage/localstorage/delete-defineproperty-removal.html:
Update test to log more information about what its doing and log it to the DOM rather
than the console, to make comparing results in browsers easier. Also, note in the
bug that the results are wrong, and have been wrong, due to https://webkit.org/b/172687.

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

33 files changed:
LayoutTests/ChangeLog
LayoutTests/js/dom/named-property-deleter-expected.txt [new file with mode: 0644]
LayoutTests/js/dom/named-property-deleter.html [new file with mode: 0644]
LayoutTests/storage/domstorage/localstorage/delete-defineproperty-removal-expected.txt
LayoutTests/storage/domstorage/localstorage/delete-defineproperty-removal.html
Source/WebCore/ChangeLog
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/bindings/js/JSDOMAbstractOperations.h [new file with mode: 0644]
Source/WebCore/bindings/js/JSDOMStringMapCustom.cpp
Source/WebCore/bindings/js/JSStorageCustom.cpp
Source/WebCore/bindings/scripts/CodeGeneratorJS.pm
Source/WebCore/bindings/scripts/test/JS/JSTestNamedDeleterNoIdentifier.cpp [new file with mode: 0644]
Source/WebCore/bindings/scripts/test/JS/JSTestNamedDeleterNoIdentifier.h [new file with mode: 0644]
Source/WebCore/bindings/scripts/test/JS/JSTestNamedDeleterThrowingException.cpp [new file with mode: 0644]
Source/WebCore/bindings/scripts/test/JS/JSTestNamedDeleterThrowingException.h [new file with mode: 0644]
Source/WebCore/bindings/scripts/test/JS/JSTestNamedDeleterWithIdentifier.cpp [new file with mode: 0644]
Source/WebCore/bindings/scripts/test/JS/JSTestNamedDeleterWithIdentifier.h [new file with mode: 0644]
Source/WebCore/bindings/scripts/test/JS/JSTestNamedDeleterWithIndexedGetter.cpp [new file with mode: 0644]
Source/WebCore/bindings/scripts/test/JS/JSTestNamedDeleterWithIndexedGetter.h [new file with mode: 0644]
Source/WebCore/bindings/scripts/test/JS/JSTestObj.h
Source/WebCore/bindings/scripts/test/TestNamedDeleterNoIdentifier.idl [new file with mode: 0644]
Source/WebCore/bindings/scripts/test/TestNamedDeleterThrowingException.idl [new file with mode: 0644]
Source/WebCore/bindings/scripts/test/TestNamedDeleterWithIdentifier.idl [new file with mode: 0644]
Source/WebCore/bindings/scripts/test/TestNamedDeleterWithIndexedGetter.idl [new file with mode: 0644]
Source/WebCore/crypto/mac/CryptoAlgorithmRSA_PSSMac.cpp
Source/WebCore/crypto/mac/CryptoDigestAlgorithm.h
Source/WebCore/dom/DOMStringMap.idl
Source/WebCore/dom/DatasetDOMStringMap.cpp
Source/WebCore/dom/DatasetDOMStringMap.h
Source/WebCore/page/DOMWindow.cpp
Source/WebCore/storage/Storage.cpp
Source/WebCore/storage/Storage.h
Source/WebCore/storage/Storage.idl

index c4445d3..93e50f1 100644 (file)
@@ -1,3 +1,20 @@
+2017-05-30  Sam Weinig  <sam@webkit.org>
+
+        [WebIDL] Generate named property deleters
+        https://bugs.webkit.org/show_bug.cgi?id=172688
+
+        Reviewed by Chris Dumez.
+
+        * js/dom/named-property-deleter-expected.txt: Added.
+        * js/dom/named-property-deleter.html: Added.
+        Add test for various named deleter conditions.
+
+        * storage/domstorage/localstorage/delete-defineproperty-removal-expected.txt:
+        * storage/domstorage/localstorage/delete-defineproperty-removal.html:
+        Update test to log more information about what its doing and log it to the DOM rather
+        than the console, to make comparing results in browsers easier. Also, note in the
+        bug that the results are wrong, and have been wrong, due to https://webkit.org/b/172687.
+
 2017-05-30  Youenn Fablet  <youenn@apple.com>
 
         Add support for Certificate and IceCandidatePair stats
diff --git a/LayoutTests/js/dom/named-property-deleter-expected.txt b/LayoutTests/js/dom/named-property-deleter-expected.txt
new file mode 100644 (file)
index 0000000..808bc13
--- /dev/null
@@ -0,0 +1,9 @@
+
+PASS Test that the return value of deleting properties is correct ([OverrideBuiltins] specified). 
+PASS Test that the return value of deleting numeric properties is correct ([OverrideBuiltins] specified). 
+PASS Test that deleting a property that does not exist in the map, but does on the prototype, will return true and not remove the property from the prototype ([OverrideBuiltins] specified). 
+PASS Test that the return value of deleting properties is correct ([OverrideBuiltins] not specified). 
+PASS Test that the return value of deleting numeric properties is correct ([OverrideBuiltins] not specified). 
+PASS Test that you can't delete a builtin property ([OverrideBuiltins] not specified). 
+PASS Test that deleting a property that does not exist in the map, but does on the prototype, will return true and not remove the property from the prototype ([OverrideBuiltins] not specified). 
+
diff --git a/LayoutTests/js/dom/named-property-deleter.html b/LayoutTests/js/dom/named-property-deleter.html
new file mode 100644 (file)
index 0000000..eed1297
--- /dev/null
@@ -0,0 +1,110 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="../../resources/testharness.js"></script>
+    <script src="../../resources/testharnessreport.js"></script>
+</head>
+<body>
+<script>
+    // To test a named property deleter with [OverrideBuiltins] specified, we use DOMStringMap via element.dataset.
+    test(() => {
+        let element = document.createElement("div");
+        element.dataset["a"] = "value1";
+        element.dataset["b"] = "value2";
+        
+        assert_true(delete element.dataset["a"], "Deleting a property known to be in the dataset should return true.");
+        assert_true(element.dataset["a"] == undefined, "Deleting a property known to be in the dataset should return true.");
+        assert_true(delete element.dataset["c"], "Deleting a property known NOT to be in the dataset should return true.");
+        assert_true(delete element.dataset["-invalid"], "Deleting a property known NOT to be in the dataset and invalid should return true.");
+    }, "Test that the return value of deleting properties is correct ([OverrideBuiltins] specified).");
+
+    test(() => {
+        let element = document.createElement("div");
+        element.dataset[1] = "value1";
+        element.dataset[2] = "value2";
+
+        assert_true(delete element.dataset[1], "Deleting a numeric property known to be in the dataset should return true.");
+        assert_equals(element.dataset[1], undefined, "Deleting a numeric property known to be in the dataset should remove the property.");
+        assert_true(delete element.dataset[3], "Deleting a numeric property known NOT to be in the dataset should return true.");
+    }, "Test that the return value of deleting numeric properties is correct ([OverrideBuiltins] specified).");
+
+    test((t) => {
+        t.add_cleanup(() => {
+          delete DOMStringMap.prototype["customProperty"];
+        });
+
+        let element = document.createElement("div");
+
+        DOMStringMap.prototype["customProperty"] = 'prototype-value';
+        assert_true(delete element["customProperty"], "");
+        assert_equals(DOMStringMap.prototype["customProperty"], 'prototype-value');
+    }, "Test that deleting a property that does not exist in the map, but does on the prototype, will return true and not remove the property from the prototype ([OverrideBuiltins] specified).");
+
+    // To test a named property deleter without [OverrideBuiltins] specified, we use Storage via window.sessionStorage.
+    test((t) => {
+        t.add_cleanup(() => {
+          window.sessionStorage.clear();
+        });
+        
+        window.sessionStorage.clear();
+        assert_equals(window.sessionStorage.length, 0);
+
+        window.sessionStorage["a"] = "value1";
+        window.sessionStorage["b"] = "value2";
+
+        assert_true(delete window.sessionStorage["a"], "Deleting a property known to be in the dataset should return true.");
+        assert_true(window.sessionStorage["a"] == undefined, "Deleting a property known to be in the dataset should return true.");
+        assert_true(delete window.sessionStorage["c"], "Deleting a property known NOT to be in the dataset should return true.");
+    }, "Test that the return value of deleting properties is correct ([OverrideBuiltins] not specified).");
+
+    test((t) => {
+        t.add_cleanup(() => {
+          window.sessionStorage.clear();
+        });
+        
+        window.sessionStorage.clear();
+        assert_equals(window.sessionStorage.length, 0);
+
+        window.sessionStorage[1] = "value1";
+        window.sessionStorage[2] = "value2";
+
+        assert_true(delete window.sessionStorage[1], "Deleting a numeric property known to be in the dataset should return true.");
+        assert_equals(window.sessionStorage[1], undefined, "Deleting a numeric property known to be in the dataset should remove the property.");
+        assert_true(delete window.sessionStorage[3], "Deleting a numeric property known NOT to be in the dataset should return true.");
+    }, "Test that the return value of deleting numeric properties is correct ([OverrideBuiltins] not specified).");
+
+    test((t) => {
+        t.add_cleanup(() => {
+          window.sessionStorage.clear();
+        });
+        
+        window.sessionStorage.clear();
+        assert_equals(window.sessionStorage.length, 0);
+
+        window.sessionStorage['a'] = "value1";
+        window.sessionStorage['b'] = "value2";
+
+        // First note that trying to set the builtin, length in this case, does not work.
+        let currentLength = window.sessionStorage['length'];
+        window.sessionStorage['length'] = 'value3';
+        assert_equals(window.sessionStorage['length'], currentLength);
+
+        // Attempting to delete it also does not work.
+        assert_true(delete window.sessionStorage['length'], "Deleting a builtin property returns true.");
+        assert_equals(window.sessionStorage['length'], currentLength);
+    }, "Test that you can't delete a builtin property ([OverrideBuiltins] not specified).");
+
+    test((t) => {
+        t.add_cleanup(() => {
+          window.sessionStorage.clear();
+          delete Storage.prototype["customProperty"];
+        });
+
+        Storage.prototype["customProperty"] = 'prototype-value';
+        assert_true(delete window.sessionStorage["customProperty"], "Deleting the a property known to exist on the prototype but not in the map should return true.");
+        assert_equals(Storage.prototype["customProperty"], 'prototype-value');
+
+    }, "Test that deleting a property that does not exist in the map, but does on the prototype, will return true and not remove the property from the prototype ([OverrideBuiltins] not specified).");
+</script>
+</body>
+</html>
index 2bea589..6ac38e8 100644 (file)
@@ -1,10 +1,32 @@
-CONSOLE MESSAGE: line 12: 
-CONSOLE MESSAGE: line 15: 1
-CONSOLE MESSAGE: line 18: 1
-CONSOLE MESSAGE: line 21: 1,2
-CONSOLE MESSAGE: line 24: 1,2
-CONSOLE MESSAGE: line 27: 1,2,Test
-CONSOLE MESSAGE: line 30: 1,2,Test
-CONSOLE MESSAGE: line 33: 1,2,Test,Test1
-CONSOLE MESSAGE: line 36: 1,2,Test,Test1
+localStorage.clear()
+Object.getOwnPropertyNames(localStorage) is ()
+
+Object.defineProperty(localStorage, '1', {value: 'present'})
+Object.getOwnPropertyNames(localStorage) is (1)
+localStorage.getItem('1') is null
+
+delete localStorage[1]
+Object.getOwnPropertyNames(localStorage) is (1)
+
+Object.defineProperty(localStorage, '2', {value: 'present',  configurable: true})
+Object.getOwnPropertyNames(localStorage) is (1,2)
+localStorage.getItem('2') is null
+
+delete localStorage[2]
+Object.getOwnPropertyNames(localStorage) is (1)
+
+Object.defineProperty(localStorage, 'Test', {value: 'present',  configurable: true})
+Object.getOwnPropertyNames(localStorage) is (1,Test)
+localStorage.getItem('Test') is null
+
+delete localStorage['Test']
+Object.getOwnPropertyNames(localStorage) is (1)
+
+Object.defineProperty(localStorage, 'Test1', {value: 'present'})
+Object.getOwnPropertyNames(localStorage) is (1,Test1)
+localStorage.getItem('Test1') is null
+
+delete localStorage['Test1']
+Object.getOwnPropertyNames(localStorage) is (1,Test1)
+
 
index c4114f4..1c28df5 100644 (file)
@@ -1,40 +1,59 @@
+<pre id='console'></pre>
 <script>
 function runTest() {
+    function log(msg)
+    {
+        document.getElementById('console').append(msg + '\n');
+    }
+
+    function logAndEval(str)
+    {
+        log(str);
+        eval(str);
+    }
+
     if (window.testRunner)
        testRunner.dumpAsText();
 
     if (!window.localStorage) {
-        console.log("window.localStorage DOES NOT exist");
+        log("window.localStorage DOES NOT exist");
         return;
     }
 
-    localStorage.clear();
-    console.log(Object.getOwnPropertyNames(localStorage));
+    logAndEval("localStorage.clear()");
+    log("Object.getOwnPropertyNames(localStorage) is (" + Object.getOwnPropertyNames(localStorage) + ")\n");
     
-    Object.defineProperty(localStorage, "1", {value: "present"});
-    console.log(Object.getOwnPropertyNames(localStorage));
+    logAndEval("Object.defineProperty(localStorage, '1', {value: 'present'})");
+    log("Object.getOwnPropertyNames(localStorage) is (" + Object.getOwnPropertyNames(localStorage) + ")");
+    // FIXME: This is incorrect. It should return 'present'. See https://webkit.org/b/172687.
+    log("localStorage.getItem('1') is " + localStorage.getItem('1') + "\n");
     
-    delete localStorage[1];
-    console.log(Object.getOwnPropertyNames(localStorage));
+    logAndEval("delete localStorage[1]");
+    log("Object.getOwnPropertyNames(localStorage) is (" + Object.getOwnPropertyNames(localStorage) + ")\n");
     
-    Object.defineProperty(localStorage, "2", {value: "present",  configurable: true});
-    console.log(Object.getOwnPropertyNames(localStorage));
+    logAndEval("Object.defineProperty(localStorage, '2', {value: 'present',  configurable: true})");
+    log("Object.getOwnPropertyNames(localStorage) is (" + Object.getOwnPropertyNames(localStorage) + ")");
+    // FIXME: This is incorrect. It should return 'present'. See https://webkit.org/b/172687.
+    log("localStorage.getItem('2') is " + localStorage.getItem('2') + "\n");
     
-    delete localStorage[2];
-    console.log(Object.getOwnPropertyNames(localStorage));
+    logAndEval("delete localStorage[2]");
+    log("Object.getOwnPropertyNames(localStorage) is (" + Object.getOwnPropertyNames(localStorage) + ")\n");
 
-    Object.defineProperty(localStorage, "Test", {value: "present",  configurable: true});
-    console.log(Object.getOwnPropertyNames(localStorage));
+    logAndEval("Object.defineProperty(localStorage, 'Test', {value: 'present',  configurable: true})");
+    log("Object.getOwnPropertyNames(localStorage) is (" + Object.getOwnPropertyNames(localStorage) + ")");
+    // FIXME: This is incorrect. It should return 'present'. See https://webkit.org/b/172687.
+    log("localStorage.getItem('Test') is " + localStorage.getItem('Test') + "\n");
   
-    delete localStorage["Test"];
-    console.log(Object.getOwnPropertyNames(localStorage));
+    logAndEval("delete localStorage['Test']");
+    log("Object.getOwnPropertyNames(localStorage) is (" + Object.getOwnPropertyNames(localStorage) + ")\n");
 
-    Object.defineProperty(localStorage, "Test1", {value: "present"});
-    console.log(Object.getOwnPropertyNames(localStorage));
+    logAndEval("Object.defineProperty(localStorage, 'Test1', {value: 'present'})");
+    log("Object.getOwnPropertyNames(localStorage) is (" + Object.getOwnPropertyNames(localStorage) + ")");
+    // FIXME: This is incorrect. It should return 'present'. See https://webkit.org/b/172687.
+    log("localStorage.getItem('Test1') is " + localStorage.getItem('Test1') + "\n");
   
-    delete localStorage["Test1"];
-    console.log(Object.getOwnPropertyNames(localStorage));
-
+    logAndEval("delete localStorage['Test1']");
+    log("Object.getOwnPropertyNames(localStorage) is (" + Object.getOwnPropertyNames(localStorage) + ")\n");
 }
 </script>
 <body onload="runTest();">
index b92f641..63a873c 100644 (file)
@@ -1,3 +1,99 @@
+2017-05-30  Sam Weinig  <sam@webkit.org>
+
+        [WebIDL] Generate named property deleters
+        https://bugs.webkit.org/show_bug.cgi?id=172688
+
+        Reviewed by Chris Dumez.
+
+        Test: js/dom/named-property-deleter.html
+
+        * WebCore.xcodeproj/project.pbxproj:
+        Add new file, JSDOMAbstractOperations.h
+
+        * bindings/js/JSDOMAbstractOperations.h: Added.
+        (WebCore::isVisibleNamedProperty):
+        Add an implementation of the abstract operation WebIDL calls the 'named property visibility algorithm'.
+        It is used by many WebIDL algorithms, but currently I am only using this implementation for deleters.
+        In the future, we should try and move the other property access generators to use it as well.
+
+        * bindings/js/JSDOMStringMapCustom.cpp:
+        (WebCore::JSDOMStringMap::deleteProperty): Deleted.
+        (WebCore::JSDOMStringMap::deletePropertyByIndex): Deleted.
+        * bindings/js/JSStorageCustom.cpp:
+        (WebCore::JSStorage::deleteProperty): Deleted.
+        (WebCore::JSStorage::deletePropertyByIndex): Deleted.
+        Remove now generated deleteProperty and deletePropertyByIndex implementations.
+
+        * bindings/scripts/CodeGeneratorJS.pm:
+        (GenerateDeletePropertyCommon):
+        (GenerateDeletePropertyDefinition):
+        (GenerateDeletePropertyByIndexDefinition):
+        (GenerateNamedDeleterDefinition):
+        Added generation for named deleters. We generate both deleteProperty and deletePropertyByIndex.
+
+        (InstanceOverridesDelete):
+        Add predicate for whether the header should declare deleteProperty and deletePropertyByIndex.
+
+        (GenerateHeader):
+        Move property access hook declarations closer to each other. Use new InstanceOverridesDelete
+        predicate for deleteProperty and deletePropertyByIndex.
+        (GenerateImplementation):
+        Add call to generate named deleter if one exists.
+
+        (GenerateConstructorHelperMethods):
+        Remove an old FIXME that that was no longer true, there are no more interfaces that inherit from
+        an interface with [NoInterfaceObject].
+
+        * dom/DOMStringMap.idl:
+        Removes CustomDeleteProperty and sorts extended attributes.
+
+        * dom/DatasetDOMStringMap.h:
+        * dom/DatasetDOMStringMap.cpp:
+        (WebCore::DatasetDOMStringMap::isSupportedPropertyName):
+        Added. This is a bindings support function (much like supportedPropertyNames()) that is
+        used JSDOMAbstractOperations.h's isVisibleNamedProperty.
+
+        (WebCore::DatasetDOMStringMap::supportedPropertyNames):
+        Convert to an early return.
+
+        (WebCore::DatasetDOMStringMap::deleteNamedProperty):
+        (WebCore::DatasetDOMStringMap::deleteItem): Deleted.
+        Renamed deleteItem to deleteNamedProperty, which is the name the bindings use for deleter
+        operations without an identifier.
+
+        * page/DOMWindow.cpp:
+        (WebCore::DOMWindow::sessionStorage):
+        Fix incorrect indentation that bothered me.
+
+        * storage/Storage.cpp:
+        * storage/Storage.h:
+        - Remove isDisabledByPrivateBrowsing(), which had no definition.
+        - Add isSupportedPropertyName(), which the deleter code (via the isVisibleNamedProperty algorithm)
+          needs.
+        
+        * storage/Storage.idl:
+        Removes CustomDeleteProperty, sorts the extended attributes, adds 'deleter' special 
+        to the removeItem operation and adds a commented out 'setter' special to the 'setItem'
+        operation.
+
+        * bindings/scripts/test/JS/JSTestObj.h:
+        Update result for declarations moving around.
+
+        * bindings/scripts/test/JS/JSTestNamedDeleterNoIdentifier.cpp: Added.
+        * bindings/scripts/test/JS/JSTestNamedDeleterNoIdentifier.h: Added.
+        * bindings/scripts/test/JS/JSTestNamedDeleterThrowingException.cpp: Added.
+        * bindings/scripts/test/JS/JSTestNamedDeleterThrowingException.h: Added.
+        * bindings/scripts/test/JS/JSTestNamedDeleterWithIdentifier.cpp: Added.
+        * bindings/scripts/test/JS/JSTestNamedDeleterWithIdentifier.h: Added.
+        * bindings/scripts/test/JS/JSTestNamedDeleterWithIndexedGetter.cpp: Added.
+        * bindings/scripts/test/JS/JSTestNamedDeleterWithIndexedGetter.h: Added.
+        * bindings/scripts/test/TestNamedDeleterNoIdentifier.idl: Added.
+        * bindings/scripts/test/TestNamedDeleterThrowingException.idl: Added.
+        * bindings/scripts/test/TestNamedDeleterWithIdentifier.idl: Added.
+        * bindings/scripts/test/TestNamedDeleterWithIndexedGetter.idl: Added.
+        Add new tests for named deleters.
+
 2017-05-30  Joseph Pecoraro  <pecoraro@apple.com>
 
         Web Inspector: images dragged from Inspector to Desktop are named "Unknown.png"
index e364065..86a26a8 100644 (file)
                77A17A7B12F2890B004E02F6 /* GraphicsTypes3D.h in Headers */ = {isa = PBXBuildFile; fileRef = 77A17A7A12F2890B004E02F6 /* GraphicsTypes3D.h */; settings = {ATTRIBUTES = (Private, ); }; };
                77A17AA612F28B2A004E02F6 /* JSOESVertexArrayObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 77A17AA212F28B2A004E02F6 /* JSOESVertexArrayObject.cpp */; };
                77A17AA712F28B2A004E02F6 /* JSOESVertexArrayObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 77A17AA312F28B2A004E02F6 /* JSOESVertexArrayObject.h */; };
-               77D5100D1ED5E29500DA4C87 /* CredentialCreationOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 77AAD6851ECFBD3900BFA2D1 /* CredentialCreationOptions.h */; };
+               77AAD6821ECF8D3800BFA2D1 /* FederatedCredential.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 77AAD6811ECF8D3800BFA2D1 /* FederatedCredential.cpp */; };
+               77D50FF41ED4D98D00DA4C87 /* JSFederatedCredentialInit.h in Headers */ = {isa = PBXBuildFile; fileRef = 77534FF21ED4C96B00A9646E /* JSFederatedCredentialInit.h */; };
+               77D50FF51ED4D99100DA4C87 /* JSFederatedCredentialInit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 77534FF11ED4C96B00A9646E /* JSFederatedCredentialInit.cpp */; };
+               77D50FF61ED4D99B00DA4C87 /* JSFederatedCredential.h in Headers */ = {isa = PBXBuildFile; fileRef = 77534FF01ED4C96B00A9646E /* JSFederatedCredential.h */; };
+               77D50FF71ED4D99D00DA4C87 /* JSFederatedCredential.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 77534FEF1ED4C96B00A9646E /* JSFederatedCredential.cpp */; };
+               77D50FF81ED4D9A000DA4C87 /* JSPasswordCredentialData.h in Headers */ = {isa = PBXBuildFile; fileRef = 77534FF41ED4C99F00A9646E /* JSPasswordCredentialData.h */; };
+               77D50FF91ED4D9A400DA4C87 /* JSPasswordCredentialData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 77534FF31ED4C99F00A9646E /* JSPasswordCredentialData.cpp */; };
+               77D510021ED4F71800DA4C87 /* JSCredentialUserData.h in Headers */ = {isa = PBXBuildFile; fileRef = 77D510011ED4F70C00DA4C87 /* JSCredentialUserData.h */; };
+               77D510031ED4F71B00DA4C87 /* JSCredentialUserData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 77D510001ED4F70C00DA4C87 /* JSCredentialUserData.cpp */; };
+               77D510041ED4F71E00DA4C87 /* JSCredentialRequestOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 77D50FFF1ED4F70C00DA4C87 /* JSCredentialRequestOptions.h */; };
+               77D510051ED4F72200DA4C87 /* JSCredentialRequestOptions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 77D50FFE1ED4F70C00DA4C87 /* JSCredentialRequestOptions.cpp */; };
+               77D510061ED4F72500DA4C87 /* JSCredentialCreationOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 77D50FFD1ED4F70C00DA4C87 /* JSCredentialCreationOptions.h */; };
+               77D510071ED4F72700DA4C87 /* JSCredentialCreationOptions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 77D50FFC1ED4F70C00DA4C87 /* JSCredentialCreationOptions.cpp */; };
+               77D5100A1ED5E28500DA4C87 /* FederatedCredentialRequestOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 77D510091ED5E26F00DA4C87 /* FederatedCredentialRequestOptions.h */; };
                77D5100B1ED5E28800DA4C87 /* CredentialRequestOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 77D50FFB1ED4F16C00DA4C87 /* CredentialRequestOptions.h */; };
-               77D510191ED715AC00DA4C87 /* CredentialsContainer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 77D510181ED7159900DA4C87 /* CredentialsContainer.cpp */; };
-               77D510171ED6022200DA4C87 /* CredentialsContainer.h in Headers */ = {isa = PBXBuildFile; fileRef = 77D510161ED6021B00DA4C87 /* CredentialsContainer.h */; };
+               77D5100C1ED5E29000DA4C87 /* PasswordCredentialData.h in Headers */ = {isa = PBXBuildFile; fileRef = 77CD16801ED3C32A009E9536 /* PasswordCredentialData.h */; };
+               77D5100D1ED5E29500DA4C87 /* CredentialCreationOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 77AAD6851ECFBD3900BFA2D1 /* CredentialCreationOptions.h */; };
                77D5100E1ED5E29B00DA4C87 /* CredentialUserData.h in Headers */ = {isa = PBXBuildFile; fileRef = 77AAD67D1ECDE8FB00BFA2D1 /* CredentialUserData.h */; };
-               77AAD6821ECF8D3800BFA2D1 /* FederatedCredential.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 77AAD6811ECF8D3800BFA2D1 /* FederatedCredential.cpp */; };
                77D5100F1ED5E2A200DA4C87 /* FederatedCredential.h in Headers */ = {isa = PBXBuildFile; fileRef = 77AAD6801ECF6C4100BFA2D1 /* FederatedCredential.h */; };
                77D510101ED5E2C900DA4C87 /* FederatedCredentialInit.h in Headers */ = {isa = PBXBuildFile; fileRef = 77CD167E1ED3BE11009E9536 /* FederatedCredentialInit.h */; };
-               77D5100A1ED5E28500DA4C87 /* FederatedCredentialRequestOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 77D510091ED5E26F00DA4C87 /* FederatedCredentialRequestOptions.h */; };
-               77D510071ED4F72700DA4C87 /* JSCredentialCreationOptions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 77D50FFC1ED4F70C00DA4C87 /* JSCredentialCreationOptions.cpp */; };
-               77D510061ED4F72500DA4C87 /* JSCredentialCreationOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 77D50FFD1ED4F70C00DA4C87 /* JSCredentialCreationOptions.h */; };
-               77D510051ED4F72200DA4C87 /* JSCredentialRequestOptions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 77D50FFE1ED4F70C00DA4C87 /* JSCredentialRequestOptions.cpp */; };
-               77D510041ED4F71E00DA4C87 /* JSCredentialRequestOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 77D50FFF1ED4F70C00DA4C87 /* JSCredentialRequestOptions.h */; };
-               77D5101D1ED722C300DA4C87 /* JSCredentialsContainer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 77D5101A1ED722B500DA4C87 /* JSCredentialsContainer.cpp */; };
-               77D5101C1ED722BF00DA4C87 /* JSCredentialsContainer.h in Headers */ = {isa = PBXBuildFile; fileRef = 77D5101B1ED722B500DA4C87 /* JSCredentialsContainer.h */; };
-               77D510031ED4F71B00DA4C87 /* JSCredentialUserData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 77D510001ED4F70C00DA4C87 /* JSCredentialUserData.cpp */; };
-               77D510021ED4F71800DA4C87 /* JSCredentialUserData.h in Headers */ = {isa = PBXBuildFile; fileRef = 77D510011ED4F70C00DA4C87 /* JSCredentialUserData.h */; };
-               77D50FF71ED4D99D00DA4C87 /* JSFederatedCredential.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 77534FEF1ED4C96B00A9646E /* JSFederatedCredential.cpp */; };
-               77D50FF61ED4D99B00DA4C87 /* JSFederatedCredential.h in Headers */ = {isa = PBXBuildFile; fileRef = 77534FF01ED4C96B00A9646E /* JSFederatedCredential.h */; };
-               77D50FF51ED4D99100DA4C87 /* JSFederatedCredentialInit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 77534FF11ED4C96B00A9646E /* JSFederatedCredentialInit.cpp */; };
-               77D50FF41ED4D98D00DA4C87 /* JSFederatedCredentialInit.h in Headers */ = {isa = PBXBuildFile; fileRef = 77534FF21ED4C96B00A9646E /* JSFederatedCredentialInit.h */; };
-               77D510141ED5F4F100DA4C87 /* JSFederatedCredentialRequestOptions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 77D510111ED5F4E700DA4C87 /* JSFederatedCredentialRequestOptions.cpp */; };
                77D510131ED5F4ED00DA4C87 /* JSFederatedCredentialRequestOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 77D510121ED5F4E700DA4C87 /* JSFederatedCredentialRequestOptions.h */; };
-               77D510261ED74B5C00DA4C87 /* JSNavigatorCredentials.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 77D510231ED74B5500DA4C87 /* JSNavigatorCredentials.cpp */; };
-               77D510251ED74B5800DA4C87 /* JSNavigatorCredentials.h in Headers */ = {isa = PBXBuildFile; fileRef = 77D510241ED74B5500DA4C87 /* JSNavigatorCredentials.h */; };
-               77D50FF91ED4D9A400DA4C87 /* JSPasswordCredentialData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 77534FF31ED4C99F00A9646E /* JSPasswordCredentialData.cpp */; };
-               77D50FF81ED4D9A000DA4C87 /* JSPasswordCredentialData.h in Headers */ = {isa = PBXBuildFile; fileRef = 77534FF41ED4C99F00A9646E /* JSPasswordCredentialData.h */; };
-               77D5100C1ED5E29000DA4C87 /* PasswordCredentialData.h in Headers */ = {isa = PBXBuildFile; fileRef = 77CD16801ED3C32A009E9536 /* PasswordCredentialData.h */; };
-               77D510221ED7364500DA4C87 /* NavigatorCredentials.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 77D510211ED7340A00DA4C87 /* NavigatorCredentials.cpp */; };
+               77D510141ED5F4F100DA4C87 /* JSFederatedCredentialRequestOptions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 77D510111ED5F4E700DA4C87 /* JSFederatedCredentialRequestOptions.cpp */; };
+               77D510171ED6022200DA4C87 /* CredentialsContainer.h in Headers */ = {isa = PBXBuildFile; fileRef = 77D510161ED6021B00DA4C87 /* CredentialsContainer.h */; };
+               77D510191ED715AC00DA4C87 /* CredentialsContainer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 77D510181ED7159900DA4C87 /* CredentialsContainer.cpp */; };
+               77D5101C1ED722BF00DA4C87 /* JSCredentialsContainer.h in Headers */ = {isa = PBXBuildFile; fileRef = 77D5101B1ED722B500DA4C87 /* JSCredentialsContainer.h */; };
+               77D5101D1ED722C300DA4C87 /* JSCredentialsContainer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 77D5101A1ED722B500DA4C87 /* JSCredentialsContainer.cpp */; };
                77D510201ED72D5F00DA4C87 /* NavigatorCredentials.h in Headers */ = {isa = PBXBuildFile; fileRef = 77D5101F1ED72D5C00DA4C87 /* NavigatorCredentials.h */; };
+               77D510221ED7364500DA4C87 /* NavigatorCredentials.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 77D510211ED7340A00DA4C87 /* NavigatorCredentials.cpp */; };
+               77D510251ED74B5800DA4C87 /* JSNavigatorCredentials.h in Headers */ = {isa = PBXBuildFile; fileRef = 77D510241ED74B5500DA4C87 /* JSNavigatorCredentials.h */; };
+               77D510261ED74B5C00DA4C87 /* JSNavigatorCredentials.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 77D510231ED74B5500DA4C87 /* JSNavigatorCredentials.cpp */; };
                77EF62F312F9DB7400C77BD2 /* JSWebGLVertexArrayObjectOES.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 77EF62F112F9DB7400C77BD2 /* JSWebGLVertexArrayObjectOES.cpp */; };
                77EF62F412F9DB7400C77BD2 /* JSWebGLVertexArrayObjectOES.h in Headers */ = {isa = PBXBuildFile; fileRef = 77EF62F212F9DB7400C77BD2 /* JSWebGLVertexArrayObjectOES.h */; };
                78D02BC5154A18DF00B62D05 /* CSSPropertyAnimation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 78D02BC3154A18DF00B62D05 /* CSSPropertyAnimation.cpp */; };
                7C522D4B15B477E8009B7C95 /* InspectorOverlay.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C522D4915B477E8009B7C95 /* InspectorOverlay.cpp */; };
                7C5343FC17B74B63004232F0 /* JSMediaQueryListListener.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C5343FA17B74B63004232F0 /* JSMediaQueryListListener.cpp */; };
                7C5343FD17B74B63004232F0 /* JSMediaQueryListListener.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C5343FB17B74B63004232F0 /* JSMediaQueryListListener.h */; };
+               7C57BFE71EDE2F6100534A48 /* JSDOMAbstractOperations.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C57BFE61EDE2F5B00534A48 /* JSDOMAbstractOperations.h */; settings = {ATTRIBUTES = (Private, ); }; };
                7C5F28FB1A827D8400C0F31F /* HTMLAttachmentElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C5F28F91A827D8400C0F31F /* HTMLAttachmentElement.cpp */; };
                7C5F28FC1A827D8400C0F31F /* HTMLAttachmentElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C5F28FA1A827D8400C0F31F /* HTMLAttachmentElement.h */; settings = {ATTRIBUTES = (Private, ); }; };
                7C6522EF1E00A4C700677F22 /* ApplePayPaymentMethod.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C6522EC1E00A4C700677F22 /* ApplePayPaymentMethod.h */; };
                7728694D14F8882500F484DC /* EXTTextureFilterAnisotropic.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = EXTTextureFilterAnisotropic.idl; sourceTree = "<group>"; };
                7728698114FD9ADA00F484DC /* JSEXTTextureFilterAnisotropic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSEXTTextureFilterAnisotropic.cpp; sourceTree = "<group>"; };
                7728698214FD9ADA00F484DC /* JSEXTTextureFilterAnisotropic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSEXTTextureFilterAnisotropic.h; sourceTree = "<group>"; };
+               77534FEF1ED4C96B00A9646E /* JSFederatedCredential.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSFederatedCredential.cpp; sourceTree = "<group>"; };
+               77534FF01ED4C96B00A9646E /* JSFederatedCredential.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSFederatedCredential.h; sourceTree = "<group>"; };
+               77534FF11ED4C96B00A9646E /* JSFederatedCredentialInit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSFederatedCredentialInit.cpp; sourceTree = "<group>"; };
+               77534FF21ED4C96B00A9646E /* JSFederatedCredentialInit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSFederatedCredentialInit.h; sourceTree = "<group>"; };
+               77534FF31ED4C99F00A9646E /* JSPasswordCredentialData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSPasswordCredentialData.cpp; sourceTree = "<group>"; };
+               77534FF41ED4C99F00A9646E /* JSPasswordCredentialData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSPasswordCredentialData.h; sourceTree = "<group>"; };
                77A17A6E12F28182004E02F6 /* OESVertexArrayObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OESVertexArrayObject.cpp; sourceTree = "<group>"; };
                77A17A6F12F28182004E02F6 /* OESVertexArrayObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OESVertexArrayObject.h; sourceTree = "<group>"; };
                77A17A7012F28182004E02F6 /* OESVertexArrayObject.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = OESVertexArrayObject.idl; sourceTree = "<group>"; };
                77A17A7A12F2890B004E02F6 /* GraphicsTypes3D.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GraphicsTypes3D.h; sourceTree = "<group>"; };
                77A17AA212F28B2A004E02F6 /* JSOESVertexArrayObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSOESVertexArrayObject.cpp; sourceTree = "<group>"; };
                77A17AA312F28B2A004E02F6 /* JSOESVertexArrayObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSOESVertexArrayObject.h; sourceTree = "<group>"; };
-               77AAD6831ECFB66200BFA2D1 /* CredentialCreationOptions.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CredentialCreationOptions.idl; sourceTree = "<group>"; };
-               77AAD6851ECFBD3900BFA2D1 /* CredentialCreationOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CredentialCreationOptions.h; sourceTree = "<group>"; };
-               77D50FFB1ED4F16C00DA4C87 /* CredentialRequestOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CredentialRequestOptions.h; sourceTree = "<group>"; };
-               77D50FFA1ED4EC7800DA4C87 /* CredentialRequestOptions.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CredentialRequestOptions.idl; sourceTree = "<group>"; };
-               77D510181ED7159900DA4C87 /* CredentialsContainer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CredentialsContainer.cpp; sourceTree = "<group>"; };
-               77D510161ED6021B00DA4C87 /* CredentialsContainer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CredentialsContainer.h; sourceTree = "<group>"; };
-               77D510151ED6001B00DA4C87 /* CredentialsContainer.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CredentialsContainer.idl; sourceTree = "<group>"; };
                77AAD67C1ECCF06E00BFA2D1 /* CredentialUserData.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CredentialUserData.idl; sourceTree = "<group>"; };
                77AAD67D1ECDE8FB00BFA2D1 /* CredentialUserData.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CredentialUserData.h; sourceTree = "<group>"; };
-               77AAD6811ECF8D3800BFA2D1 /* FederatedCredential.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FederatedCredential.cpp; sourceTree = "<group>"; };
-               77AAD6801ECF6C4100BFA2D1 /* FederatedCredential.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FederatedCredential.h; sourceTree = "<group>"; };
                77AAD67F1ECF6A3D00BFA2D1 /* FederatedCredential.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = FederatedCredential.idl; sourceTree = "<group>"; };
-               77D510091ED5E26F00DA4C87 /* FederatedCredentialRequestOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FederatedCredentialRequestOptions.h; sourceTree = "<group>"; };
-               77D510081ED5E21800DA4C87 /* FederatedCredentialRequestOptions.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = FederatedCredentialRequestOptions.idl; sourceTree = "<group>"; };
-               77CD167E1ED3BE11009E9536 /* FederatedCredentialInit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FederatedCredentialInit.h; sourceTree = "<group>"; };
+               77AAD6801ECF6C4100BFA2D1 /* FederatedCredential.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FederatedCredential.h; sourceTree = "<group>"; };
+               77AAD6811ECF8D3800BFA2D1 /* FederatedCredential.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FederatedCredential.cpp; sourceTree = "<group>"; };
+               77AAD6831ECFB66200BFA2D1 /* CredentialCreationOptions.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CredentialCreationOptions.idl; sourceTree = "<group>"; };
+               77AAD6851ECFBD3900BFA2D1 /* CredentialCreationOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CredentialCreationOptions.h; sourceTree = "<group>"; };
                77CD167D1ED3BDB8009E9536 /* FederatedCredentialInit.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = FederatedCredentialInit.idl; sourceTree = "<group>"; };
+               77CD167E1ED3BE11009E9536 /* FederatedCredentialInit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FederatedCredentialInit.h; sourceTree = "<group>"; };
+               77CD167F1ED3C2DB009E9536 /* PasswordCredentialData.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = PasswordCredentialData.idl; sourceTree = "<group>"; };
+               77CD16801ED3C32A009E9536 /* PasswordCredentialData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PasswordCredentialData.h; sourceTree = "<group>"; };
+               77D50FFA1ED4EC7800DA4C87 /* CredentialRequestOptions.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CredentialRequestOptions.idl; sourceTree = "<group>"; };
+               77D50FFB1ED4F16C00DA4C87 /* CredentialRequestOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CredentialRequestOptions.h; sourceTree = "<group>"; };
                77D50FFC1ED4F70C00DA4C87 /* JSCredentialCreationOptions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCredentialCreationOptions.cpp; sourceTree = "<group>"; };
                77D50FFD1ED4F70C00DA4C87 /* JSCredentialCreationOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCredentialCreationOptions.h; sourceTree = "<group>"; };
                77D50FFE1ED4F70C00DA4C87 /* JSCredentialRequestOptions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCredentialRequestOptions.cpp; sourceTree = "<group>"; };
                77D50FFF1ED4F70C00DA4C87 /* JSCredentialRequestOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCredentialRequestOptions.h; sourceTree = "<group>"; };
-               77D5101A1ED722B500DA4C87 /* JSCredentialsContainer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCredentialsContainer.cpp; sourceTree = "<group>"; };
-               77D5101B1ED722B500DA4C87 /* JSCredentialsContainer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCredentialsContainer.h; sourceTree = "<group>"; };
                77D510001ED4F70C00DA4C87 /* JSCredentialUserData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCredentialUserData.cpp; sourceTree = "<group>"; };
                77D510011ED4F70C00DA4C87 /* JSCredentialUserData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCredentialUserData.h; sourceTree = "<group>"; };
-               77534FEF1ED4C96B00A9646E /* JSFederatedCredential.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSFederatedCredential.cpp; sourceTree = "<group>"; };
-               77534FF01ED4C96B00A9646E /* JSFederatedCredential.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSFederatedCredential.h; sourceTree = "<group>"; };
-               77534FF11ED4C96B00A9646E /* JSFederatedCredentialInit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSFederatedCredentialInit.cpp; sourceTree = "<group>"; };
-               77534FF21ED4C96B00A9646E /* JSFederatedCredentialInit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSFederatedCredentialInit.h; sourceTree = "<group>"; };
+               77D510081ED5E21800DA4C87 /* FederatedCredentialRequestOptions.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = FederatedCredentialRequestOptions.idl; sourceTree = "<group>"; };
+               77D510091ED5E26F00DA4C87 /* FederatedCredentialRequestOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FederatedCredentialRequestOptions.h; sourceTree = "<group>"; };
                77D510111ED5F4E700DA4C87 /* JSFederatedCredentialRequestOptions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSFederatedCredentialRequestOptions.cpp; sourceTree = "<group>"; };
                77D510121ED5F4E700DA4C87 /* JSFederatedCredentialRequestOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSFederatedCredentialRequestOptions.h; sourceTree = "<group>"; };
+               77D510151ED6001B00DA4C87 /* CredentialsContainer.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CredentialsContainer.idl; sourceTree = "<group>"; };
+               77D510161ED6021B00DA4C87 /* CredentialsContainer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CredentialsContainer.h; sourceTree = "<group>"; };
+               77D510181ED7159900DA4C87 /* CredentialsContainer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CredentialsContainer.cpp; sourceTree = "<group>"; };
+               77D5101A1ED722B500DA4C87 /* JSCredentialsContainer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCredentialsContainer.cpp; sourceTree = "<group>"; };
+               77D5101B1ED722B500DA4C87 /* JSCredentialsContainer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCredentialsContainer.h; sourceTree = "<group>"; };
+               77D5101E1ED72BDB00DA4C87 /* NavigatorCredentials.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = NavigatorCredentials.idl; sourceTree = "<group>"; };
+               77D5101F1ED72D5C00DA4C87 /* NavigatorCredentials.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NavigatorCredentials.h; sourceTree = "<group>"; };
+               77D510211ED7340A00DA4C87 /* NavigatorCredentials.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NavigatorCredentials.cpp; sourceTree = "<group>"; wrapsLines = 1; };
                77D510231ED74B5500DA4C87 /* JSNavigatorCredentials.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSNavigatorCredentials.cpp; sourceTree = "<group>"; };
                77D510241ED74B5500DA4C87 /* JSNavigatorCredentials.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSNavigatorCredentials.h; sourceTree = "<group>"; };
-               77534FF31ED4C99F00A9646E /* JSPasswordCredentialData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSPasswordCredentialData.cpp; sourceTree = "<group>"; };
-               77534FF41ED4C99F00A9646E /* JSPasswordCredentialData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSPasswordCredentialData.h; sourceTree = "<group>"; };
-               77D510211ED7340A00DA4C87 /* NavigatorCredentials.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NavigatorCredentials.cpp; sourceTree = "<group>"; wrapsLines = 1; };
-               77D5101F1ED72D5C00DA4C87 /* NavigatorCredentials.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NavigatorCredentials.h; sourceTree = "<group>"; };
-               77D5101E1ED72BDB00DA4C87 /* NavigatorCredentials.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = NavigatorCredentials.idl; sourceTree = "<group>"; };
-               77CD16801ED3C32A009E9536 /* PasswordCredentialData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PasswordCredentialData.h; sourceTree = "<group>"; };
-               77CD167F1ED3C2DB009E9536 /* PasswordCredentialData.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = PasswordCredentialData.idl; sourceTree = "<group>"; };
                77EF62F112F9DB7400C77BD2 /* JSWebGLVertexArrayObjectOES.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSWebGLVertexArrayObjectOES.cpp; sourceTree = "<group>"; };
                77EF62F212F9DB7400C77BD2 /* JSWebGLVertexArrayObjectOES.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSWebGLVertexArrayObjectOES.h; sourceTree = "<group>"; };
                78D02BC3154A18DF00B62D05 /* CSSPropertyAnimation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CSSPropertyAnimation.cpp; sourceTree = "<group>"; };
                7C522D4A15B478B2009B7C95 /* InspectorOverlay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorOverlay.h; sourceTree = "<group>"; };
                7C5343FA17B74B63004232F0 /* JSMediaQueryListListener.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSMediaQueryListListener.cpp; sourceTree = "<group>"; };
                7C5343FB17B74B63004232F0 /* JSMediaQueryListListener.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = JSMediaQueryListListener.h; sourceTree = "<group>"; };
+               7C57BFE61EDE2F5B00534A48 /* JSDOMAbstractOperations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSDOMAbstractOperations.h; sourceTree = "<group>"; };
                7C5BEA391E9EE77100CC517B /* NavigatorConcurrentHardware.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = NavigatorConcurrentHardware.idl; sourceTree = "<group>"; };
                7C5BEA3A1E9EE77100CC517B /* NavigatorID.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = NavigatorID.idl; sourceTree = "<group>"; };
                7C5BEA3B1E9EE77100CC517B /* NavigatorLanguage.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = NavigatorLanguage.idl; sourceTree = "<group>"; };
                                E125F83C182411E700D84CD9 /* JSCryptoOperationData.h */,
                                9BD4E9141C462872005065BC /* JSCustomElementInterface.cpp */,
                                9BD4E9151C462872005065BC /* JSCustomElementInterface.h */,
+                               7C57BFE61EDE2F5B00534A48 /* JSDOMAbstractOperations.h */,
                                7C8139A31ED6281D00CE26E8 /* JSDOMAttribute.h */,
                                93B70D4809EB0C7C009D8468 /* JSDOMBinding.h */,
                                41DEFCB21E56C1B9000D9E5F /* JSDOMBindingInternals.js */,
                                9920398318B95BC600B39AF9 /* UserInputBridge.h in Headers */,
                                71C916081D1483A300ACA47D /* UserInterfaceLayoutDirection.h in Headers */,
                                078E092E17D14D1C00420AA1 /* UserMediaClient.h in Headers */,
+                               7C57BFE71EDE2F6100534A48 /* JSDOMAbstractOperations.h in Headers */,
                                078E092F17D14D1C00420AA1 /* UserMediaController.h in Headers */,
                                078E093017D14D1C00420AA1 /* UserMediaRequest.h in Headers */,
                                7C3B79721908757B00B47A2D /* UserMessageHandler.h in Headers */,
diff --git a/Source/WebCore/bindings/js/JSDOMAbstractOperations.h b/Source/WebCore/bindings/js/JSDOMAbstractOperations.h
new file mode 100644 (file)
index 0000000..79abb00
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 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
+ * 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. AND ITS CONTRIBUTORS ``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 ITS 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.
+ */
+
+#pragma once
+
+#include "JSDOMConvertStrings.h"
+
+namespace WebCore {
+
+// Implementations of the abstract operations defined at
+// https://heycam.github.io/webidl/#legacy-platform-object-abstract-ops
+
+
+// An implementation of the 'named property visibility algorithm'
+// https://heycam.github.io/webidl/#dfn-named-property-visibility
+template<bool overrideBuiltins, class JSClass>
+static bool isVisibleNamedProperty(JSC::ExecState& state, JSClass& thisObject, JSC::PropertyName propertyName)
+{
+    // FIXME: It seems unfortunate that have to do two lookups for the property name,
+    // one for isSupportedPropertyName and one by the user of this algorithm to access
+    // that property. It would be nice if we could smuggle the result, or an iterator
+    // out so the duplicate lookup could be avoided.
+
+    // NOTE: While it is not specified, a Symbol can never be a 'supported property
+    // name' so we check that first.
+    if (propertyName.isSymbol())
+        return false;
+
+    auto& impl = thisObject.wrapped();
+
+    // 1. If P is not a supported property name of O, then return false.
+    if (!impl.isSupportedPropertyName(propertyNameToString(propertyName)))
+        return false;
+    
+    // 2. If O has an own property named P, then return false.
+    JSC::PropertySlot slot { &thisObject, JSC::PropertySlot::InternalMethodType::GetOwnProperty };
+    if (JSC::JSObject::getOwnPropertySlot(&thisObject, &state, propertyName, slot))
+        return false;
+    
+    // 3. If O implements an interface that has the [OverrideBuiltins] extended attribute, then return true.
+    if (overrideBuiltins)
+        return true;
+
+    // 4. Initialize prototype to be the value of the internal [[Prototype]] property of O.
+    // 5. While prototype is not null:
+    //    1. If prototype is not a named properties object, and prototype has an own property named P, then return false.
+    //    2. Set prototype to be the value of the internal [[Prototype]] property of prototype.
+    auto prototype = thisObject.getPrototypeDirect();
+    if (prototype.isObject() && JSC::asObject(prototype)->getPropertySlot(&state, propertyName, slot))
+        return false;
+
+    // 6. Return true.
+    return true;
+}
+
+}
index b3cc70d..397c951 100644 (file)
@@ -37,19 +37,6 @@ using namespace JSC;
 
 namespace WebCore {
 
-bool JSDOMStringMap::deleteProperty(JSCell* cell, ExecState* state, PropertyName propertyName)
-{
-    CustomElementReactionStack customElementReactionStack;
-    if (propertyName.isSymbol())
-        return Base::deleteProperty(cell, state, propertyName);
-    return jsCast<JSDOMStringMap*>(cell)->wrapped().deleteItem(propertyNameToString(propertyName));
-}
-
-bool JSDOMStringMap::deletePropertyByIndex(JSCell* cell, ExecState* state, unsigned index)
-{
-    return deleteProperty(cell, state, Identifier::from(state, index));
-}
-
 bool JSDOMStringMap::putDelegate(ExecState* state, PropertyName propertyName, JSValue value, PutPropertySlot&, bool& putResult)
 {
     VM& vm = state->vm();
index 0440443..ce7482d 100644 (file)
@@ -36,33 +36,6 @@ using namespace JSC;
 
 namespace WebCore {
 
-bool JSStorage::deleteProperty(JSCell* cell, ExecState* state, PropertyName propertyName)
-{
-    auto& thisObject = *jsCast<JSStorage*>(cell);
-
-    // Only perform the custom delete if the object doesn't have a native property by this name.
-    // Since hasProperty() would end up calling canGetItemsForName() and be fooled, we need to check
-    // the native property slots manually.
-    PropertySlot slot(&thisObject, PropertySlot::InternalMethodType::GetOwnProperty);
-
-    JSValue prototype = thisObject.getPrototypeDirect();
-    if (prototype.isObject() && asObject(prototype)->getPropertySlot(state, propertyName, slot))
-        return Base::deleteProperty(&thisObject, state, propertyName);
-
-    if (propertyName.isSymbol())
-        return Base::deleteProperty(&thisObject, state, propertyName);
-
-    VM& vm = state->vm();
-    auto scope = DECLARE_THROW_SCOPE(vm);
-    propagateException(*state, scope, thisObject.wrapped().removeItem(propertyNameToString(propertyName)));
-    return true;
-}
-
-bool JSStorage::deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned propertyName)
-{
-    return deleteProperty(cell, exec, Identifier::from(exec, propertyName));
-}
-
 void JSStorage::getOwnPropertyNames(JSObject* object, ExecState* state, PropertyNameArray& propertyNames, EnumerationMode mode)
 {
     VM& vm = state->vm();
@@ -92,6 +65,9 @@ bool JSStorage::putDelegate(ExecState* state, PropertyName propertyName, JSValue
     VM& vm = state->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
 
+    if (propertyName.isSymbol())
+        return false;
+
     // Only perform the custom put if the object doesn't have a native property by this name.
     // Since hasProperty() would end up calling canGetItemsForName() and be fooled, we need to check
     // the native property slots manually.
@@ -101,10 +77,7 @@ bool JSStorage::putDelegate(ExecState* state, PropertyName propertyName, JSValue
     if (prototype.isObject() && asObject(prototype)->getPropertySlot(state, propertyName, slot))
         return false;
 
-    if (propertyName.isSymbol())
-        return false;
-
-    String stringValue = value.toWTFString(state);
+    auto stringValue = convert<IDLDOMString>(*state, value);
     RETURN_IF_EXCEPTION(scope, true);
 
     auto setItemResult = wrapped().setItem(propertyNameToString(propertyName), stringValue);
index 2f18cdf..a5b1fa7 100644 (file)
@@ -730,6 +730,173 @@ sub GeneratePutByIndex
     return @output;
 }
 
+sub GenerateDeletePropertyCommon
+{
+    my ($outputArray, $interface, $className, $operation, $conditional) = @_;
+    
+    # This implements step 2 of https://heycam.github.io/webidl/#legacy-platform-object-delete
+    # so it can be shared between the generation of deleteProperty and deletePropertyByIndex.
+
+    # 2. If O supports named properties, O does not implement an interface with the
+    #    [Global] or [PrimaryGlobal] extended attribute and the result of calling the
+    #    named property visibility algorithm with property name P and object O is true,
+    #    then:
+    assert("Named property deleters are not allowed without a corresponding named property getter.") if !GetNamedGetterOperation($interface);
+    assert("Named property deleters are not allowed on global object interfaces.") if IsGlobalOrPrimaryGlobalInterface($interface);
+
+    AddToImplIncludes("JSDOMAbstractOperations.h", $conditional);
+    my $overrideBuiltin = $interface->extendedAttributes->{OverrideBuiltins} ? "true" : "false";
+    push(@$outputArray, "    if (isVisibleNamedProperty<${overrideBuiltin}>(*state, thisObject, propertyName)) {\n");
+
+    if ($operation->extendedAttributes->{CEReactions}) {
+        push(@$outputArray, "        CustomElementReactionStack customElementReactionStack;\n");
+        AddToImplIncludes("CustomElementReactionQueue.h", $conditional);
+    }
+
+    # 2.1. If O does not implement an interface with a named property deleter, then return false.
+    # 2.2. Let operation be the operation used to declare the named property deleter.
+    # NOTE: We only add a deleteProperty implementation of we have a named property deleter.
+
+    # 2.3. If operation was defined without an identifier, then:
+    #      1. Perform the steps listed in the interface description to delete an existing named
+    #         property with P as the name.
+    #      2. If the steps indicated that the deletion failed, then return false.
+    # 2.4. Otherwise, operation was defined with an identifier:
+    #      1. Perform the steps listed in the description of operation with P as the only argument
+    #         value.
+    #      2. If operation was declared with a return type of boolean and the steps returned false,
+    #         then return false.
+
+    my $functionImplementationName = $operation->extendedAttributes->{ImplementedAs} || $codeGenerator->WK_lcfirst($operation->name) || "deleteNamedProperty";
+    my $functionCall = "impl." . $functionImplementationName . "(propertyNameToString(propertyName))";
+
+    # NOTE: We expect the implementation function of named deleters without an identifier to
+    #       return either bool or ExceptionOr<bool>. the implementation function of named deleters
+    #       with an identifier have no restriction, but if the return value of the operation is
+    #       boolean, we return that value, otherwise it is ignored (as per section 4.2).
+
+    if ($operation->extendedAttributes->{MayThrowException}) {
+        push(@$outputArray, "        auto result = ${functionCall};\n");
+        push(@$outputArray, "        if (result.hasException()) {\n");
+        push(@$outputArray, "            auto throwScope = DECLARE_THROW_SCOPE(state->vm());\n");
+        push(@$outputArray, "            propagateException(*state, throwScope, result.releaseException());\n");
+        push(@$outputArray, "            return true;\n");
+        push(@$outputArray, "        }\n\n");
+
+        if (!$operation->name || $operation->name && $operation->type->name eq "boolean") {
+            push(@$outputArray, "        return result.releaseReturnValue();\n");
+        } else {
+            push(@$outputArray, "        return true;\n");
+        }
+    } else {
+        if (!$operation->name || $operation->name && $operation->type->name eq "boolean") {
+            push(@$outputArray, "        return ${functionCall};\n");
+        } else {
+            push(@$outputArray, "        ${functionCall};\n");
+            push(@$outputArray, "        return true;\n");
+        }
+    }
+
+    push(@$outputArray, "    }\n");
+}
+
+sub GenerateDeletePropertyDefinition
+{
+    my ($outputArray, $interface, $className, $operation, $conditional) = @_;
+
+    # This implements https://heycam.github.io/webidl/#legacy-platform-object-delete for the
+    # for the deleteProperty override hook.
+
+    push(@$outputArray, "bool ${className}::deleteProperty(JSCell* cell, ExecState* state, PropertyName propertyName)\n");
+    push(@$outputArray, "{\n");
+
+    push(@$outputArray, "    auto& thisObject = *jsCast<${className}*>(cell);\n");
+    push(@$outputArray, "    auto& impl = thisObject.wrapped();\n");
+
+    # 1. If O supports indexed properties and P is an array index property name, then:
+    #    1. Let index be the result of calling ToUint32(P).
+    #    2. If index is not a supported property index, then return true.
+    #    3. Return false.
+    if (GetIndexedGetterOperation($interface)) {
+        push(@$outputArray, "    if (auto index = parseIndex(propertyName))\n");
+        push(@$outputArray, "        return !impl.isSupportedPropertyIndex(index.value());\n");
+    }
+
+    # GenerateDeletePropertyCommon implements step 2.
+    GenerateDeletePropertyCommon($outputArray, $interface, $className, $operation, $conditional);
+
+    # FIXME: Instead of calling down Base::deleteProperty, perhaps we should implement
+    # the remained of the algorithm ourselves.
+    push(@$outputArray, "    return Base::deleteProperty(cell, state, propertyName);\n");
+    push(@$outputArray, "}\n\n");
+}
+
+sub GenerateDeletePropertyByIndexDefinition
+{
+    my ($outputArray, $interface, $className, $operation, $conditional) = @_;
+
+    # This implements https://heycam.github.io/webidl/#legacy-platform-object-delete for the
+    # for the deletePropertyByIndex override hook.
+
+    push(@$outputArray, "bool ${className}::deletePropertyByIndex(JSCell* cell, ExecState* state, unsigned index)\n");
+    push(@$outputArray, "{\n");
+
+    push(@$outputArray, "    auto& thisObject = *jsCast<${className}*>(cell);\n");
+    push(@$outputArray, "    auto& impl = thisObject.wrapped();\n");
+
+    # 1. If O supports indexed properties and P is an array index property name, then:
+    #    1. Let index be the result of calling ToUint32(P).
+    #    2. If index is not a supported property index, then return true.
+    #    3. Return false.
+
+    # NOTE: For deletePropertyByIndex, if there is an indexed getter, checking isSupportedPropertyIndex()
+    #       is all that needs to be done, no need to generate the .
+
+    if (GetIndexedGetterOperation($interface)) {
+        push(@$outputArray, "    return !impl.isSupportedPropertyIndex(index);\n");
+    } else {
+        push(@$outputArray, "    auto propertyName = Identifier::from(state, index);\n");
+
+        # GenerateDeletePropertyCommon implements step 2.
+        GenerateDeletePropertyCommon($outputArray, $interface, $className, $operation, $conditional);
+
+        # FIXME: Instead of calling down Base::deletePropertyByIndex, perhaps we should implement
+        # the remaineder of the algoritm (steps 3 and 4) ourselves.
+        
+        # 3. If O has an own property with name P, then:
+        #    1. If the property is not configurable, then return false.
+        #    2. Otherwise, remove the property from O.
+        # 3. Return true.
+        
+        push(@$outputArray, "    return Base::deletePropertyByIndex(cell, state, index);\n");
+    }
+
+    push(@$outputArray, "}\n\n");
+}
+
+
+sub GenerateNamedDeleterDefinition
+{
+    my ($outputArray, $interface, $className, $operation) = @_;
+
+    # This implements https://heycam.github.io/webidl/#legacy-platform-object-delete using
+    # the deleteProperty and deletePropertyByIndex override hooks.
+
+    assert("Named property deleters are not allowed without a corresponding named property getter.") if !GetNamedGetterOperation($interface);
+    assert("Named property deleters are not allowed on global object interfaces.") if IsGlobalOrPrimaryGlobalInterface($interface);
+
+    my $conditional = $operation->extendedAttributes->{Conditional};
+    if ($conditional) {
+        my $conditionalString = $codeGenerator->GenerateConditionalStringFromAttributeValue($conditional);
+        push(@$outputArray, "#if ${conditionalString}\n\n");;
+    }
+
+    GenerateDeletePropertyDefinition($outputArray, $interface, $className, $operation, $conditional);
+    GenerateDeletePropertyByIndexDefinition($outputArray, $interface, $className, $operation, $conditional);
+
+    push(@implContent, "#endif\n\n") if $conditional;
+}
+
 sub GenerateHeaderContentHeader
 {
     my $interface = shift;
@@ -1153,6 +1320,13 @@ sub InstanceOverridesPut
         || GetNamedSetterOperation($interface);
 }
 
+sub InstanceOverridesDelete
+{
+    my $interface = shift;
+    return $interface->extendedAttributes->{CustomDeleteProperty}
+        || GetNamedDeleterOperation($interface);
+}
+
 sub PrototypeHasStaticPropertyTable
 {
     my $interface = shift;
@@ -1826,6 +2000,8 @@ sub GenerateHeader
     push(@headerContent, "    static const bool needsDestruction = false;\n\n") if IsDOMGlobalObject($interface);
 
     $structureFlags{"JSC::HasStaticPropertyTable"} = 1 if InstancePropertyCount($interface) > 0;
+    $structureFlags{"JSC::NewImpurePropertyFiresWatchpoints"} = 1 if $interface->extendedAttributes->{NewImpurePropertyFiresWatchpoints};
+    $structureFlags{"JSC::IsImmutablePrototypeExoticObject"} = 1 if $interface->extendedAttributes->{IsImmutablePrototypeExoticObject};
 
     # Prototype
     unless (ShouldUseGlobalObjectPrototype($interface)) {
@@ -1861,8 +2037,6 @@ sub GenerateHeader
         || $interface->extendedAttributes->{CustomGetOwnPropertySlot}
         || $hasNamedGetter;
 
-    my $hasGetter = InstanceOverridesGetOwnPropertySlot($interface);
-
     if ($hasNamedGetter) {
         if ($interface->extendedAttributes->{OverrideBuiltins}) {
             $structureFlags{"JSC::GetOwnPropertySlotIsImpure"} = 1;
@@ -1870,11 +2044,9 @@ sub GenerateHeader
             $structureFlags{"JSC::GetOwnPropertySlotIsImpureForPropertyAbsence"} = 1;
         }
     }
-    $structureFlags{"JSC::NewImpurePropertyFiresWatchpoints"} = 1 if $interface->extendedAttributes->{NewImpurePropertyFiresWatchpoints};
-    $structureFlags{"JSC::IsImmutablePrototypeExoticObject"} = 1 if $interface->extendedAttributes->{IsImmutablePrototypeExoticObject};
 
-    # Getters
-    if ($hasGetter) {
+    my $overridesGet = InstanceOverridesGetOwnPropertySlot($interface);
+    if ($overridesGet) {
         push(@headerContent, "    static bool getOwnPropertySlot(JSC::JSObject*, JSC::ExecState*, JSC::PropertyName, JSC::PropertySlot&);\n");
         $structureFlags{"JSC::OverridesGetOwnPropertySlot"} = 1;
 
@@ -1885,13 +2057,23 @@ sub GenerateHeader
     }
 
     my $overridesPut = InstanceOverridesPutDeclaration($interface);
-
-    # Getters
     if ($overridesPut) {
         push(@headerContent, "    static bool put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName, JSC::JSValue, JSC::PutPropertySlot&);\n");
         push(@headerContent, "    static bool putByIndex(JSC::JSCell*, JSC::ExecState*, unsigned propertyName, JSC::JSValue, bool shouldThrow);\n");
     }
 
+    if (InstanceOverridesDelete($interface)) {
+        push(@headerContent, "    static bool deleteProperty(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName);\n");
+        push(@headerContent, "    static bool deletePropertyByIndex(JSC::JSCell*, JSC::ExecState*, unsigned);\n");
+    }
+
+    # 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;
+    }
+
     if (!$hasParent) {
         push(@headerContent, "    static void destroy(JSC::JSCell*);\n");
     }
@@ -1927,17 +2109,6 @@ sub GenerateHeader
     # Custom pushEventHandlerScope function
     push(@headerContent, "    JSC::JSScope* pushEventHandlerScope(JSC::ExecState*, JSC::JSScope*) const;\n\n") if $interface->extendedAttributes->{JSCustomPushEventHandlerScope};
 
-    # 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};
-    push(@headerContent, "    static bool deletePropertyByIndex(JSC::JSCell*, JSC::ExecState*, unsigned);\n") if $interface->extendedAttributes->{CustomDeleteProperty};
-
     # Custom getPropertyNames function exists on DOMWindow
     if ($interfaceName eq "DOMWindow") {
         push(@headerContent, "    static void getPropertyNames(JSC::JSObject*, JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode = JSC::EnumerationMode());\n");
@@ -3624,10 +3795,8 @@ sub GenerateImplementation
         push(@implContent, "}\n\n");
     }
 
-    my $hasGetter = InstanceOverridesGetOwnPropertySlot($interface);
-
-    # Attributes
-    if ($hasGetter) {
+    my $overridesGet = InstanceOverridesGetOwnPropertySlot($interface);
+    if ($overridesGet) {
         if (!$interface->extendedAttributes->{CustomGetOwnPropertySlot}) {
             push(@implContent, GenerateGetOwnPropertySlotBody($interface, $className, $indexedGetterOperation, $namedGetterOperation));
         }
@@ -3658,6 +3827,11 @@ sub GenerateImplementation
         }
     }
 
+    my $namedDeleterOperation = GetNamedDeleterOperation($interface);
+    if ($namedDeleterOperation) {
+        GenerateNamedDeleterDefinition(\@implContent, $interface, $className, $namedDeleterOperation);
+    }
+
     if ($numAttributes > 0) {
         AddToImplIncludes("JSDOMAttribute.h");
 
@@ -6323,10 +6497,10 @@ sub GenerateConstructorHelperMethods
     # otherwise use FunctionPrototype: http://heycam.github.io/webidl/#interface-object
     push(@$outputArray, "template<> JSValue ${constructorClassName}::prototypeForStructure(JSC::VM& vm, const JSDOMGlobalObject& globalObject)\n");
     push(@$outputArray, "{\n");
-    # FIXME: IDL does not allow an interface without [NoInterfaceObject] to inherit one that is marked as [NoInterfaceObject]
-    # so we should be able to use our parent's interface object no matter what. However, some of our IDL files (e.g. CanvasRenderingContext2D)
-    # are not valid so we need this check for now.
-    if ($interface->parentType && !$codeGenerator->GetInterfaceExtendedAttributesFromName($interface->parentType->name)->{NoInterfaceObject}) {
+
+    assert("An interface cannot inherit from another interface that is marked as [NoInterfaceObject]") if $interface->parentType && $codeGenerator->GetInterfaceExtendedAttributesFromName($interface->parentType->name)->{NoInterfaceObject};
+
+    if ($interface->parentType) {
         my $parentClassName = "JS" . $interface->parentType->name;
         push(@$outputArray, "    return ${parentClassName}::getConstructor(vm, &globalObject);\n");
     } else {
diff --git a/Source/WebCore/bindings/scripts/test/JS/JSTestNamedDeleterNoIdentifier.cpp b/Source/WebCore/bindings/scripts/test/JS/JSTestNamedDeleterNoIdentifier.cpp
new file mode 100644 (file)
index 0000000..1f3461b
--- /dev/null
@@ -0,0 +1,281 @@
+/*
+    This file is part of the WebKit open source project.
+    This file has been generated by generate-bindings.pl. DO NOT MODIFY!
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+#include "JSTestNamedDeleterNoIdentifier.h"
+
+#include "JSDOMAbstractOperations.h"
+#include "JSDOMBinding.h"
+#include "JSDOMConstructorNotConstructable.h"
+#include "JSDOMConvert.h"
+#include "JSDOMExceptionHandling.h"
+#include "JSDOMWrapperCache.h"
+#include <runtime/FunctionPrototype.h>
+#include <wtf/GetPtr.h>
+
+using namespace JSC;
+
+namespace WebCore {
+
+// Attributes
+
+JSC::EncodedJSValue jsTestNamedDeleterNoIdentifierConstructor(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
+bool setJSTestNamedDeleterNoIdentifierConstructor(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);
+
+class JSTestNamedDeleterNoIdentifierPrototype : public JSC::JSNonFinalObject {
+public:
+    using Base = JSC::JSNonFinalObject;
+    static JSTestNamedDeleterNoIdentifierPrototype* create(JSC::VM& vm, JSDOMGlobalObject* globalObject, JSC::Structure* structure)
+    {
+        JSTestNamedDeleterNoIdentifierPrototype* ptr = new (NotNull, JSC::allocateCell<JSTestNamedDeleterNoIdentifierPrototype>(vm.heap)) JSTestNamedDeleterNoIdentifierPrototype(vm, globalObject, structure);
+        ptr->finishCreation(vm);
+        return ptr;
+    }
+
+    DECLARE_INFO;
+    static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
+    {
+        return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());
+    }
+
+private:
+    JSTestNamedDeleterNoIdentifierPrototype(JSC::VM& vm, JSC::JSGlobalObject*, JSC::Structure* structure)
+        : JSC::JSNonFinalObject(vm, structure)
+    {
+    }
+
+    void finishCreation(JSC::VM&);
+};
+
+using JSTestNamedDeleterNoIdentifierConstructor = JSDOMConstructorNotConstructable<JSTestNamedDeleterNoIdentifier>;
+
+template<> JSValue JSTestNamedDeleterNoIdentifierConstructor::prototypeForStructure(JSC::VM& vm, const JSDOMGlobalObject& globalObject)
+{
+    UNUSED_PARAM(vm);
+    return globalObject.functionPrototype();
+}
+
+template<> void JSTestNamedDeleterNoIdentifierConstructor::initializeProperties(VM& vm, JSDOMGlobalObject& globalObject)
+{
+    putDirect(vm, vm.propertyNames->prototype, JSTestNamedDeleterNoIdentifier::prototype(vm, globalObject), DontDelete | ReadOnly | DontEnum);
+    putDirect(vm, vm.propertyNames->name, jsNontrivialString(&vm, String(ASCIILiteral("TestNamedDeleterNoIdentifier"))), ReadOnly | DontEnum);
+    putDirect(vm, vm.propertyNames->length, jsNumber(0), ReadOnly | DontEnum);
+}
+
+template<> const ClassInfo JSTestNamedDeleterNoIdentifierConstructor::s_info = { "TestNamedDeleterNoIdentifier", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSTestNamedDeleterNoIdentifierConstructor) };
+
+/* Hash table for prototype */
+
+static const HashTableValue JSTestNamedDeleterNoIdentifierPrototypeTableValues[] =
+{
+    { "constructor", DontEnum, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestNamedDeleterNoIdentifierConstructor), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSTestNamedDeleterNoIdentifierConstructor) } },
+};
+
+const ClassInfo JSTestNamedDeleterNoIdentifierPrototype::s_info = { "TestNamedDeleterNoIdentifierPrototype", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSTestNamedDeleterNoIdentifierPrototype) };
+
+void JSTestNamedDeleterNoIdentifierPrototype::finishCreation(VM& vm)
+{
+    Base::finishCreation(vm);
+    reifyStaticProperties(vm, JSTestNamedDeleterNoIdentifierPrototypeTableValues, *this);
+}
+
+const ClassInfo JSTestNamedDeleterNoIdentifier::s_info = { "TestNamedDeleterNoIdentifier", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSTestNamedDeleterNoIdentifier) };
+
+JSTestNamedDeleterNoIdentifier::JSTestNamedDeleterNoIdentifier(Structure* structure, JSDOMGlobalObject& globalObject, Ref<TestNamedDeleterNoIdentifier>&& impl)
+    : JSDOMWrapper<TestNamedDeleterNoIdentifier>(structure, globalObject, WTFMove(impl))
+{
+}
+
+void JSTestNamedDeleterNoIdentifier::finishCreation(VM& vm)
+{
+    Base::finishCreation(vm);
+    ASSERT(inherits(vm, info()));
+
+}
+
+JSObject* JSTestNamedDeleterNoIdentifier::createPrototype(VM& vm, JSDOMGlobalObject& globalObject)
+{
+    return JSTestNamedDeleterNoIdentifierPrototype::create(vm, &globalObject, JSTestNamedDeleterNoIdentifierPrototype::createStructure(vm, &globalObject, globalObject.objectPrototype()));
+}
+
+JSObject* JSTestNamedDeleterNoIdentifier::prototype(VM& vm, JSDOMGlobalObject& globalObject)
+{
+    return getDOMPrototype<JSTestNamedDeleterNoIdentifier>(vm, globalObject);
+}
+
+JSValue JSTestNamedDeleterNoIdentifier::getConstructor(VM& vm, const JSGlobalObject* globalObject)
+{
+    return getDOMConstructor<JSTestNamedDeleterNoIdentifierConstructor>(vm, *jsCast<const JSDOMGlobalObject*>(globalObject));
+}
+
+void JSTestNamedDeleterNoIdentifier::destroy(JSC::JSCell* cell)
+{
+    JSTestNamedDeleterNoIdentifier* thisObject = static_cast<JSTestNamedDeleterNoIdentifier*>(cell);
+    thisObject->JSTestNamedDeleterNoIdentifier::~JSTestNamedDeleterNoIdentifier();
+}
+
+bool JSTestNamedDeleterNoIdentifier::getOwnPropertySlot(JSObject* object, ExecState* state, PropertyName propertyName, PropertySlot& slot)
+{
+    auto* thisObject = jsCast<JSTestNamedDeleterNoIdentifier*>(object);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
+    if (Base::getOwnPropertySlot(thisObject, state, propertyName, slot))
+        return true;
+    JSValue proto = thisObject->getPrototypeDirect();
+    if (proto.isObject() && jsCast<JSObject*>(proto)->hasProperty(state, propertyName))
+        return false;
+
+    if (thisObject->classInfo() == info() && !propertyName.isSymbol()) {
+        auto item = thisObject->wrapped().namedItem(propertyNameToAtomicString(propertyName));
+        if (!IDLDOMString::isNullValue(item)) {
+            slot.setValue(thisObject, ReadOnly, toJS<IDLDOMString>(*state, item));
+            return true;
+        }
+    }
+    return false;
+}
+
+bool JSTestNamedDeleterNoIdentifier::getOwnPropertySlotByIndex(JSObject* object, ExecState* state, unsigned index, PropertySlot& slot)
+{
+    auto* thisObject = jsCast<JSTestNamedDeleterNoIdentifier*>(object);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
+    Identifier propertyName = Identifier::from(state, index);
+    if (thisObject->classInfo() == info()) {
+        auto item = thisObject->wrapped().namedItem(propertyNameToAtomicString(propertyName));
+        if (!IDLDOMString::isNullValue(item)) {
+            slot.setValue(thisObject, ReadOnly, toJS<IDLDOMString>(*state, item));
+            return true;
+        }
+    }
+    return Base::getOwnPropertySlotByIndex(thisObject, state, index, slot);
+}
+
+void JSTestNamedDeleterNoIdentifier::getOwnPropertyNames(JSObject* object, ExecState* state, PropertyNameArray& propertyNames, EnumerationMode mode)
+{
+    auto* thisObject = jsCast<JSTestNamedDeleterNoIdentifier*>(object);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
+    for (auto& propertyName : thisObject->wrapped().supportedPropertyNames())
+        propertyNames.add(Identifier::fromString(state, propertyName));
+    Base::getOwnPropertyNames(thisObject, state, propertyNames, mode);
+}
+
+bool JSTestNamedDeleterNoIdentifier::deleteProperty(JSCell* cell, ExecState* state, PropertyName propertyName)
+{
+    auto& thisObject = *jsCast<JSTestNamedDeleterNoIdentifier*>(cell);
+    auto& impl = thisObject.wrapped();
+    if (isVisibleNamedProperty<false>(*state, thisObject, propertyName)) {
+        return impl.deleteNamedProperty(propertyNameToString(propertyName));
+    }
+    return Base::deleteProperty(cell, state, propertyName);
+}
+
+bool JSTestNamedDeleterNoIdentifier::deletePropertyByIndex(JSCell* cell, ExecState* state, unsigned index)
+{
+    auto& thisObject = *jsCast<JSTestNamedDeleterNoIdentifier*>(cell);
+    auto& impl = thisObject.wrapped();
+    auto propertyName = Identifier::from(state, index);
+    if (isVisibleNamedProperty<false>(*state, thisObject, propertyName)) {
+        return impl.deleteNamedProperty(propertyNameToString(propertyName));
+    }
+    return Base::deletePropertyByIndex(cell, state, index);
+}
+
+EncodedJSValue jsTestNamedDeleterNoIdentifierConstructor(ExecState* state, EncodedJSValue thisValue, PropertyName)
+{
+    VM& vm = state->vm();
+    auto throwScope = DECLARE_THROW_SCOPE(vm);
+    auto* prototype = jsDynamicDowncast<JSTestNamedDeleterNoIdentifierPrototype*>(vm, JSValue::decode(thisValue));
+    if (UNLIKELY(!prototype))
+        return throwVMTypeError(state, throwScope);
+    return JSValue::encode(JSTestNamedDeleterNoIdentifier::getConstructor(state->vm(), prototype->globalObject()));
+}
+
+bool setJSTestNamedDeleterNoIdentifierConstructor(ExecState* state, EncodedJSValue thisValue, EncodedJSValue encodedValue)
+{
+    VM& vm = state->vm();
+    auto throwScope = DECLARE_THROW_SCOPE(vm);
+    auto* prototype = jsDynamicDowncast<JSTestNamedDeleterNoIdentifierPrototype*>(vm, JSValue::decode(thisValue));
+    if (UNLIKELY(!prototype)) {
+        throwVMTypeError(state, throwScope);
+        return false;
+    }
+    // Shadowing a built-in constructor
+    return prototype->putDirect(state->vm(), state->propertyNames().constructor, JSValue::decode(encodedValue));
+}
+
+bool JSTestNamedDeleterNoIdentifierOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor)
+{
+    UNUSED_PARAM(handle);
+    UNUSED_PARAM(visitor);
+    return false;
+}
+
+void JSTestNamedDeleterNoIdentifierOwner::finalize(JSC::Handle<JSC::Unknown> handle, void* context)
+{
+    auto* jsTestNamedDeleterNoIdentifier = static_cast<JSTestNamedDeleterNoIdentifier*>(handle.slot()->asCell());
+    auto& world = *static_cast<DOMWrapperWorld*>(context);
+    uncacheWrapper(world, &jsTestNamedDeleterNoIdentifier->wrapped(), jsTestNamedDeleterNoIdentifier);
+}
+
+#if ENABLE(BINDING_INTEGRITY)
+#if PLATFORM(WIN)
+#pragma warning(disable: 4483)
+extern "C" { extern void (*const __identifier("??_7TestNamedDeleterNoIdentifier@WebCore@@6B@")[])(); }
+#else
+extern "C" { extern void* _ZTVN7WebCore28TestNamedDeleterNoIdentifierE[]; }
+#endif
+#endif
+
+JSC::JSValue toJSNewlyCreated(JSC::ExecState*, JSDOMGlobalObject* globalObject, Ref<TestNamedDeleterNoIdentifier>&& impl)
+{
+
+#if ENABLE(BINDING_INTEGRITY)
+    void* actualVTablePointer = *(reinterpret_cast<void**>(impl.ptr()));
+#if PLATFORM(WIN)
+    void* expectedVTablePointer = reinterpret_cast<void*>(__identifier("??_7TestNamedDeleterNoIdentifier@WebCore@@6B@"));
+#else
+    void* expectedVTablePointer = &_ZTVN7WebCore28TestNamedDeleterNoIdentifierE[2];
+#if COMPILER(CLANG)
+    // If this fails TestNamedDeleterNoIdentifier does not have a vtable, so you need to add the
+    // ImplementationLacksVTable attribute to the interface definition
+    static_assert(__is_polymorphic(TestNamedDeleterNoIdentifier), "TestNamedDeleterNoIdentifier is not polymorphic");
+#endif
+#endif
+    // If you hit this assertion you either have a use after free bug, or
+    // TestNamedDeleterNoIdentifier has subclasses. If TestNamedDeleterNoIdentifier has subclasses that get passed
+    // to toJS() we currently require TestNamedDeleterNoIdentifier you to opt out of binding hardening
+    // by adding the SkipVTableValidation attribute to the interface IDL definition
+    RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer);
+#endif
+    return createWrapper<TestNamedDeleterNoIdentifier>(globalObject, WTFMove(impl));
+}
+
+JSC::JSValue toJS(JSC::ExecState* state, JSDOMGlobalObject* globalObject, TestNamedDeleterNoIdentifier& impl)
+{
+    return wrap(state, globalObject, impl);
+}
+
+TestNamedDeleterNoIdentifier* JSTestNamedDeleterNoIdentifier::toWrapped(JSC::VM& vm, JSC::JSValue value)
+{
+    if (auto* wrapper = jsDynamicDowncast<JSTestNamedDeleterNoIdentifier*>(vm, value))
+        return &wrapper->wrapped();
+    return nullptr;
+}
+
+}
diff --git a/Source/WebCore/bindings/scripts/test/JS/JSTestNamedDeleterNoIdentifier.h b/Source/WebCore/bindings/scripts/test/JS/JSTestNamedDeleterNoIdentifier.h
new file mode 100644 (file)
index 0000000..122fdf4
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+    This file is part of the WebKit open source project.
+    This file has been generated by generate-bindings.pl. DO NOT MODIFY!
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#pragma once
+
+#include "JSDOMWrapper.h"
+#include "TestNamedDeleterNoIdentifier.h"
+#include <wtf/NeverDestroyed.h>
+
+namespace WebCore {
+
+class JSTestNamedDeleterNoIdentifier : public JSDOMWrapper<TestNamedDeleterNoIdentifier> {
+public:
+    using Base = JSDOMWrapper<TestNamedDeleterNoIdentifier>;
+    static JSTestNamedDeleterNoIdentifier* create(JSC::Structure* structure, JSDOMGlobalObject* globalObject, Ref<TestNamedDeleterNoIdentifier>&& impl)
+    {
+        JSTestNamedDeleterNoIdentifier* ptr = new (NotNull, JSC::allocateCell<JSTestNamedDeleterNoIdentifier>(globalObject->vm().heap)) JSTestNamedDeleterNoIdentifier(structure, *globalObject, WTFMove(impl));
+        ptr->finishCreation(globalObject->vm());
+        return ptr;
+    }
+
+    static JSC::JSObject* createPrototype(JSC::VM&, JSDOMGlobalObject&);
+    static JSC::JSObject* prototype(JSC::VM&, JSDOMGlobalObject&);
+    static TestNamedDeleterNoIdentifier* toWrapped(JSC::VM&, JSC::JSValue);
+    static bool getOwnPropertySlot(JSC::JSObject*, JSC::ExecState*, JSC::PropertyName, JSC::PropertySlot&);
+    static bool getOwnPropertySlotByIndex(JSC::JSObject*, JSC::ExecState*, unsigned propertyName, JSC::PropertySlot&);
+    static bool deleteProperty(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName);
+    static bool deletePropertyByIndex(JSC::JSCell*, JSC::ExecState*, unsigned);
+    static void destroy(JSC::JSCell*);
+
+    DECLARE_INFO;
+
+    static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
+    {
+        return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());
+    }
+
+    static void getOwnPropertyNames(JSC::JSObject*, JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode = JSC::EnumerationMode());
+    static JSC::JSValue getConstructor(JSC::VM&, const JSC::JSGlobalObject*);
+public:
+    static const unsigned StructureFlags = JSC::GetOwnPropertySlotIsImpureForPropertyAbsence | JSC::InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | JSC::OverridesGetOwnPropertySlot | JSC::OverridesGetPropertyNames | Base::StructureFlags;
+protected:
+    JSTestNamedDeleterNoIdentifier(JSC::Structure*, JSDOMGlobalObject&, Ref<TestNamedDeleterNoIdentifier>&&);
+
+    void finishCreation(JSC::VM&);
+};
+
+class JSTestNamedDeleterNoIdentifierOwner : public JSC::WeakHandleOwner {
+public:
+    virtual bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown>, void* context, JSC::SlotVisitor&);
+    virtual void finalize(JSC::Handle<JSC::Unknown>, void* context);
+};
+
+inline JSC::WeakHandleOwner* wrapperOwner(DOMWrapperWorld&, TestNamedDeleterNoIdentifier*)
+{
+    static NeverDestroyed<JSTestNamedDeleterNoIdentifierOwner> owner;
+    return &owner.get();
+}
+
+inline void* wrapperKey(TestNamedDeleterNoIdentifier* wrappableObject)
+{
+    return wrappableObject;
+}
+
+JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, TestNamedDeleterNoIdentifier&);
+inline JSC::JSValue toJS(JSC::ExecState* state, JSDOMGlobalObject* globalObject, TestNamedDeleterNoIdentifier* impl) { return impl ? toJS(state, globalObject, *impl) : JSC::jsNull(); }
+JSC::JSValue toJSNewlyCreated(JSC::ExecState*, JSDOMGlobalObject*, Ref<TestNamedDeleterNoIdentifier>&&);
+inline JSC::JSValue toJSNewlyCreated(JSC::ExecState* state, JSDOMGlobalObject* globalObject, RefPtr<TestNamedDeleterNoIdentifier>&& impl) { return impl ? toJSNewlyCreated(state, globalObject, impl.releaseNonNull()) : JSC::jsNull(); }
+
+template<> struct JSDOMWrapperConverterTraits<TestNamedDeleterNoIdentifier> {
+    using WrapperClass = JSTestNamedDeleterNoIdentifier;
+    using ToWrappedReturnType = TestNamedDeleterNoIdentifier*;
+};
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/scripts/test/JS/JSTestNamedDeleterThrowingException.cpp b/Source/WebCore/bindings/scripts/test/JS/JSTestNamedDeleterThrowingException.cpp
new file mode 100644 (file)
index 0000000..6c9728b
--- /dev/null
@@ -0,0 +1,295 @@
+/*
+    This file is part of the WebKit open source project.
+    This file has been generated by generate-bindings.pl. DO NOT MODIFY!
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+#include "JSTestNamedDeleterThrowingException.h"
+
+#include "JSDOMAbstractOperations.h"
+#include "JSDOMBinding.h"
+#include "JSDOMConstructorNotConstructable.h"
+#include "JSDOMConvert.h"
+#include "JSDOMExceptionHandling.h"
+#include "JSDOMWrapperCache.h"
+#include <runtime/FunctionPrototype.h>
+#include <wtf/GetPtr.h>
+
+using namespace JSC;
+
+namespace WebCore {
+
+// Attributes
+
+JSC::EncodedJSValue jsTestNamedDeleterThrowingExceptionConstructor(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
+bool setJSTestNamedDeleterThrowingExceptionConstructor(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);
+
+class JSTestNamedDeleterThrowingExceptionPrototype : public JSC::JSNonFinalObject {
+public:
+    using Base = JSC::JSNonFinalObject;
+    static JSTestNamedDeleterThrowingExceptionPrototype* create(JSC::VM& vm, JSDOMGlobalObject* globalObject, JSC::Structure* structure)
+    {
+        JSTestNamedDeleterThrowingExceptionPrototype* ptr = new (NotNull, JSC::allocateCell<JSTestNamedDeleterThrowingExceptionPrototype>(vm.heap)) JSTestNamedDeleterThrowingExceptionPrototype(vm, globalObject, structure);
+        ptr->finishCreation(vm);
+        return ptr;
+    }
+
+    DECLARE_INFO;
+    static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
+    {
+        return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());
+    }
+
+private:
+    JSTestNamedDeleterThrowingExceptionPrototype(JSC::VM& vm, JSC::JSGlobalObject*, JSC::Structure* structure)
+        : JSC::JSNonFinalObject(vm, structure)
+    {
+    }
+
+    void finishCreation(JSC::VM&);
+};
+
+using JSTestNamedDeleterThrowingExceptionConstructor = JSDOMConstructorNotConstructable<JSTestNamedDeleterThrowingException>;
+
+template<> JSValue JSTestNamedDeleterThrowingExceptionConstructor::prototypeForStructure(JSC::VM& vm, const JSDOMGlobalObject& globalObject)
+{
+    UNUSED_PARAM(vm);
+    return globalObject.functionPrototype();
+}
+
+template<> void JSTestNamedDeleterThrowingExceptionConstructor::initializeProperties(VM& vm, JSDOMGlobalObject& globalObject)
+{
+    putDirect(vm, vm.propertyNames->prototype, JSTestNamedDeleterThrowingException::prototype(vm, globalObject), DontDelete | ReadOnly | DontEnum);
+    putDirect(vm, vm.propertyNames->name, jsNontrivialString(&vm, String(ASCIILiteral("TestNamedDeleterThrowingException"))), ReadOnly | DontEnum);
+    putDirect(vm, vm.propertyNames->length, jsNumber(0), ReadOnly | DontEnum);
+}
+
+template<> const ClassInfo JSTestNamedDeleterThrowingExceptionConstructor::s_info = { "TestNamedDeleterThrowingException", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSTestNamedDeleterThrowingExceptionConstructor) };
+
+/* Hash table for prototype */
+
+static const HashTableValue JSTestNamedDeleterThrowingExceptionPrototypeTableValues[] =
+{
+    { "constructor", DontEnum, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestNamedDeleterThrowingExceptionConstructor), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSTestNamedDeleterThrowingExceptionConstructor) } },
+};
+
+const ClassInfo JSTestNamedDeleterThrowingExceptionPrototype::s_info = { "TestNamedDeleterThrowingExceptionPrototype", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSTestNamedDeleterThrowingExceptionPrototype) };
+
+void JSTestNamedDeleterThrowingExceptionPrototype::finishCreation(VM& vm)
+{
+    Base::finishCreation(vm);
+    reifyStaticProperties(vm, JSTestNamedDeleterThrowingExceptionPrototypeTableValues, *this);
+}
+
+const ClassInfo JSTestNamedDeleterThrowingException::s_info = { "TestNamedDeleterThrowingException", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSTestNamedDeleterThrowingException) };
+
+JSTestNamedDeleterThrowingException::JSTestNamedDeleterThrowingException(Structure* structure, JSDOMGlobalObject& globalObject, Ref<TestNamedDeleterThrowingException>&& impl)
+    : JSDOMWrapper<TestNamedDeleterThrowingException>(structure, globalObject, WTFMove(impl))
+{
+}
+
+void JSTestNamedDeleterThrowingException::finishCreation(VM& vm)
+{
+    Base::finishCreation(vm);
+    ASSERT(inherits(vm, info()));
+
+}
+
+JSObject* JSTestNamedDeleterThrowingException::createPrototype(VM& vm, JSDOMGlobalObject& globalObject)
+{
+    return JSTestNamedDeleterThrowingExceptionPrototype::create(vm, &globalObject, JSTestNamedDeleterThrowingExceptionPrototype::createStructure(vm, &globalObject, globalObject.objectPrototype()));
+}
+
+JSObject* JSTestNamedDeleterThrowingException::prototype(VM& vm, JSDOMGlobalObject& globalObject)
+{
+    return getDOMPrototype<JSTestNamedDeleterThrowingException>(vm, globalObject);
+}
+
+JSValue JSTestNamedDeleterThrowingException::getConstructor(VM& vm, const JSGlobalObject* globalObject)
+{
+    return getDOMConstructor<JSTestNamedDeleterThrowingExceptionConstructor>(vm, *jsCast<const JSDOMGlobalObject*>(globalObject));
+}
+
+void JSTestNamedDeleterThrowingException::destroy(JSC::JSCell* cell)
+{
+    JSTestNamedDeleterThrowingException* thisObject = static_cast<JSTestNamedDeleterThrowingException*>(cell);
+    thisObject->JSTestNamedDeleterThrowingException::~JSTestNamedDeleterThrowingException();
+}
+
+bool JSTestNamedDeleterThrowingException::getOwnPropertySlot(JSObject* object, ExecState* state, PropertyName propertyName, PropertySlot& slot)
+{
+    auto* thisObject = jsCast<JSTestNamedDeleterThrowingException*>(object);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
+    if (Base::getOwnPropertySlot(thisObject, state, propertyName, slot))
+        return true;
+    JSValue proto = thisObject->getPrototypeDirect();
+    if (proto.isObject() && jsCast<JSObject*>(proto)->hasProperty(state, propertyName))
+        return false;
+
+    if (thisObject->classInfo() == info() && !propertyName.isSymbol()) {
+        auto item = thisObject->wrapped().namedItem(propertyNameToAtomicString(propertyName));
+        if (!IDLDOMString::isNullValue(item)) {
+            slot.setValue(thisObject, ReadOnly, toJS<IDLDOMString>(*state, item));
+            return true;
+        }
+    }
+    return false;
+}
+
+bool JSTestNamedDeleterThrowingException::getOwnPropertySlotByIndex(JSObject* object, ExecState* state, unsigned index, PropertySlot& slot)
+{
+    auto* thisObject = jsCast<JSTestNamedDeleterThrowingException*>(object);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
+    Identifier propertyName = Identifier::from(state, index);
+    if (thisObject->classInfo() == info()) {
+        auto item = thisObject->wrapped().namedItem(propertyNameToAtomicString(propertyName));
+        if (!IDLDOMString::isNullValue(item)) {
+            slot.setValue(thisObject, ReadOnly, toJS<IDLDOMString>(*state, item));
+            return true;
+        }
+    }
+    return Base::getOwnPropertySlotByIndex(thisObject, state, index, slot);
+}
+
+void JSTestNamedDeleterThrowingException::getOwnPropertyNames(JSObject* object, ExecState* state, PropertyNameArray& propertyNames, EnumerationMode mode)
+{
+    auto* thisObject = jsCast<JSTestNamedDeleterThrowingException*>(object);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
+    for (auto& propertyName : thisObject->wrapped().supportedPropertyNames())
+        propertyNames.add(Identifier::fromString(state, propertyName));
+    Base::getOwnPropertyNames(thisObject, state, propertyNames, mode);
+}
+
+bool JSTestNamedDeleterThrowingException::deleteProperty(JSCell* cell, ExecState* state, PropertyName propertyName)
+{
+    auto& thisObject = *jsCast<JSTestNamedDeleterThrowingException*>(cell);
+    auto& impl = thisObject.wrapped();
+    if (isVisibleNamedProperty<false>(*state, thisObject, propertyName)) {
+        auto result = impl.deleteNamedProperty(propertyNameToString(propertyName));
+        if (result.hasException()) {
+            auto throwScope = DECLARE_THROW_SCOPE(state->vm());
+            propagateException(*state, throwScope, result.releaseException());
+            return true;
+        }
+
+        return result.releaseReturnValue();
+    }
+    return Base::deleteProperty(cell, state, propertyName);
+}
+
+bool JSTestNamedDeleterThrowingException::deletePropertyByIndex(JSCell* cell, ExecState* state, unsigned index)
+{
+    auto& thisObject = *jsCast<JSTestNamedDeleterThrowingException*>(cell);
+    auto& impl = thisObject.wrapped();
+    auto propertyName = Identifier::from(state, index);
+    if (isVisibleNamedProperty<false>(*state, thisObject, propertyName)) {
+        auto result = impl.deleteNamedProperty(propertyNameToString(propertyName));
+        if (result.hasException()) {
+            auto throwScope = DECLARE_THROW_SCOPE(state->vm());
+            propagateException(*state, throwScope, result.releaseException());
+            return true;
+        }
+
+        return result.releaseReturnValue();
+    }
+    return Base::deletePropertyByIndex(cell, state, index);
+}
+
+EncodedJSValue jsTestNamedDeleterThrowingExceptionConstructor(ExecState* state, EncodedJSValue thisValue, PropertyName)
+{
+    VM& vm = state->vm();
+    auto throwScope = DECLARE_THROW_SCOPE(vm);
+    auto* prototype = jsDynamicDowncast<JSTestNamedDeleterThrowingExceptionPrototype*>(vm, JSValue::decode(thisValue));
+    if (UNLIKELY(!prototype))
+        return throwVMTypeError(state, throwScope);
+    return JSValue::encode(JSTestNamedDeleterThrowingException::getConstructor(state->vm(), prototype->globalObject()));
+}
+
+bool setJSTestNamedDeleterThrowingExceptionConstructor(ExecState* state, EncodedJSValue thisValue, EncodedJSValue encodedValue)
+{
+    VM& vm = state->vm();
+    auto throwScope = DECLARE_THROW_SCOPE(vm);
+    auto* prototype = jsDynamicDowncast<JSTestNamedDeleterThrowingExceptionPrototype*>(vm, JSValue::decode(thisValue));
+    if (UNLIKELY(!prototype)) {
+        throwVMTypeError(state, throwScope);
+        return false;
+    }
+    // Shadowing a built-in constructor
+    return prototype->putDirect(state->vm(), state->propertyNames().constructor, JSValue::decode(encodedValue));
+}
+
+bool JSTestNamedDeleterThrowingExceptionOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor)
+{
+    UNUSED_PARAM(handle);
+    UNUSED_PARAM(visitor);
+    return false;
+}
+
+void JSTestNamedDeleterThrowingExceptionOwner::finalize(JSC::Handle<JSC::Unknown> handle, void* context)
+{
+    auto* jsTestNamedDeleterThrowingException = static_cast<JSTestNamedDeleterThrowingException*>(handle.slot()->asCell());
+    auto& world = *static_cast<DOMWrapperWorld*>(context);
+    uncacheWrapper(world, &jsTestNamedDeleterThrowingException->wrapped(), jsTestNamedDeleterThrowingException);
+}
+
+#if ENABLE(BINDING_INTEGRITY)
+#if PLATFORM(WIN)
+#pragma warning(disable: 4483)
+extern "C" { extern void (*const __identifier("??_7TestNamedDeleterThrowingException@WebCore@@6B@")[])(); }
+#else
+extern "C" { extern void* _ZTVN7WebCore33TestNamedDeleterThrowingExceptionE[]; }
+#endif
+#endif
+
+JSC::JSValue toJSNewlyCreated(JSC::ExecState*, JSDOMGlobalObject* globalObject, Ref<TestNamedDeleterThrowingException>&& impl)
+{
+
+#if ENABLE(BINDING_INTEGRITY)
+    void* actualVTablePointer = *(reinterpret_cast<void**>(impl.ptr()));
+#if PLATFORM(WIN)
+    void* expectedVTablePointer = reinterpret_cast<void*>(__identifier("??_7TestNamedDeleterThrowingException@WebCore@@6B@"));
+#else
+    void* expectedVTablePointer = &_ZTVN7WebCore33TestNamedDeleterThrowingExceptionE[2];
+#if COMPILER(CLANG)
+    // If this fails TestNamedDeleterThrowingException does not have a vtable, so you need to add the
+    // ImplementationLacksVTable attribute to the interface definition
+    static_assert(__is_polymorphic(TestNamedDeleterThrowingException), "TestNamedDeleterThrowingException is not polymorphic");
+#endif
+#endif
+    // If you hit this assertion you either have a use after free bug, or
+    // TestNamedDeleterThrowingException has subclasses. If TestNamedDeleterThrowingException has subclasses that get passed
+    // to toJS() we currently require TestNamedDeleterThrowingException you to opt out of binding hardening
+    // by adding the SkipVTableValidation attribute to the interface IDL definition
+    RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer);
+#endif
+    return createWrapper<TestNamedDeleterThrowingException>(globalObject, WTFMove(impl));
+}
+
+JSC::JSValue toJS(JSC::ExecState* state, JSDOMGlobalObject* globalObject, TestNamedDeleterThrowingException& impl)
+{
+    return wrap(state, globalObject, impl);
+}
+
+TestNamedDeleterThrowingException* JSTestNamedDeleterThrowingException::toWrapped(JSC::VM& vm, JSC::JSValue value)
+{
+    if (auto* wrapper = jsDynamicDowncast<JSTestNamedDeleterThrowingException*>(vm, value))
+        return &wrapper->wrapped();
+    return nullptr;
+}
+
+}
diff --git a/Source/WebCore/bindings/scripts/test/JS/JSTestNamedDeleterThrowingException.h b/Source/WebCore/bindings/scripts/test/JS/JSTestNamedDeleterThrowingException.h
new file mode 100644 (file)
index 0000000..57985d0
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+    This file is part of the WebKit open source project.
+    This file has been generated by generate-bindings.pl. DO NOT MODIFY!
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#pragma once
+
+#include "JSDOMWrapper.h"
+#include "TestNamedDeleterThrowingException.h"
+#include <wtf/NeverDestroyed.h>
+
+namespace WebCore {
+
+class JSTestNamedDeleterThrowingException : public JSDOMWrapper<TestNamedDeleterThrowingException> {
+public:
+    using Base = JSDOMWrapper<TestNamedDeleterThrowingException>;
+    static JSTestNamedDeleterThrowingException* create(JSC::Structure* structure, JSDOMGlobalObject* globalObject, Ref<TestNamedDeleterThrowingException>&& impl)
+    {
+        JSTestNamedDeleterThrowingException* ptr = new (NotNull, JSC::allocateCell<JSTestNamedDeleterThrowingException>(globalObject->vm().heap)) JSTestNamedDeleterThrowingException(structure, *globalObject, WTFMove(impl));
+        ptr->finishCreation(globalObject->vm());
+        return ptr;
+    }
+
+    static JSC::JSObject* createPrototype(JSC::VM&, JSDOMGlobalObject&);
+    static JSC::JSObject* prototype(JSC::VM&, JSDOMGlobalObject&);
+    static TestNamedDeleterThrowingException* toWrapped(JSC::VM&, JSC::JSValue);
+    static bool getOwnPropertySlot(JSC::JSObject*, JSC::ExecState*, JSC::PropertyName, JSC::PropertySlot&);
+    static bool getOwnPropertySlotByIndex(JSC::JSObject*, JSC::ExecState*, unsigned propertyName, JSC::PropertySlot&);
+    static bool deleteProperty(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName);
+    static bool deletePropertyByIndex(JSC::JSCell*, JSC::ExecState*, unsigned);
+    static void destroy(JSC::JSCell*);
+
+    DECLARE_INFO;
+
+    static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
+    {
+        return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());
+    }
+
+    static void getOwnPropertyNames(JSC::JSObject*, JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode = JSC::EnumerationMode());
+    static JSC::JSValue getConstructor(JSC::VM&, const JSC::JSGlobalObject*);
+public:
+    static const unsigned StructureFlags = JSC::GetOwnPropertySlotIsImpureForPropertyAbsence | JSC::InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | JSC::OverridesGetOwnPropertySlot | JSC::OverridesGetPropertyNames | Base::StructureFlags;
+protected:
+    JSTestNamedDeleterThrowingException(JSC::Structure*, JSDOMGlobalObject&, Ref<TestNamedDeleterThrowingException>&&);
+
+    void finishCreation(JSC::VM&);
+};
+
+class JSTestNamedDeleterThrowingExceptionOwner : public JSC::WeakHandleOwner {
+public:
+    virtual bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown>, void* context, JSC::SlotVisitor&);
+    virtual void finalize(JSC::Handle<JSC::Unknown>, void* context);
+};
+
+inline JSC::WeakHandleOwner* wrapperOwner(DOMWrapperWorld&, TestNamedDeleterThrowingException*)
+{
+    static NeverDestroyed<JSTestNamedDeleterThrowingExceptionOwner> owner;
+    return &owner.get();
+}
+
+inline void* wrapperKey(TestNamedDeleterThrowingException* wrappableObject)
+{
+    return wrappableObject;
+}
+
+JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, TestNamedDeleterThrowingException&);
+inline JSC::JSValue toJS(JSC::ExecState* state, JSDOMGlobalObject* globalObject, TestNamedDeleterThrowingException* impl) { return impl ? toJS(state, globalObject, *impl) : JSC::jsNull(); }
+JSC::JSValue toJSNewlyCreated(JSC::ExecState*, JSDOMGlobalObject*, Ref<TestNamedDeleterThrowingException>&&);
+inline JSC::JSValue toJSNewlyCreated(JSC::ExecState* state, JSDOMGlobalObject* globalObject, RefPtr<TestNamedDeleterThrowingException>&& impl) { return impl ? toJSNewlyCreated(state, globalObject, impl.releaseNonNull()) : JSC::jsNull(); }
+
+template<> struct JSDOMWrapperConverterTraits<TestNamedDeleterThrowingException> {
+    using WrapperClass = JSTestNamedDeleterThrowingException;
+    using ToWrappedReturnType = TestNamedDeleterThrowingException*;
+};
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/scripts/test/JS/JSTestNamedDeleterWithIdentifier.cpp b/Source/WebCore/bindings/scripts/test/JS/JSTestNamedDeleterWithIdentifier.cpp
new file mode 100644 (file)
index 0000000..761743b
--- /dev/null
@@ -0,0 +1,312 @@
+/*
+    This file is part of the WebKit open source project.
+    This file has been generated by generate-bindings.pl. DO NOT MODIFY!
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+#include "JSTestNamedDeleterWithIdentifier.h"
+
+#include "JSDOMAbstractOperations.h"
+#include "JSDOMBinding.h"
+#include "JSDOMConstructorNotConstructable.h"
+#include "JSDOMConvert.h"
+#include "JSDOMExceptionHandling.h"
+#include "JSDOMOperation.h"
+#include "JSDOMWrapperCache.h"
+#include <runtime/FunctionPrototype.h>
+#include <wtf/GetPtr.h>
+
+using namespace JSC;
+
+namespace WebCore {
+
+// Functions
+
+JSC::EncodedJSValue JSC_HOST_CALL jsTestNamedDeleterWithIdentifierPrototypeFunctionRemove(JSC::ExecState*);
+
+// Attributes
+
+JSC::EncodedJSValue jsTestNamedDeleterWithIdentifierConstructor(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
+bool setJSTestNamedDeleterWithIdentifierConstructor(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);
+
+class JSTestNamedDeleterWithIdentifierPrototype : public JSC::JSNonFinalObject {
+public:
+    using Base = JSC::JSNonFinalObject;
+    static JSTestNamedDeleterWithIdentifierPrototype* create(JSC::VM& vm, JSDOMGlobalObject* globalObject, JSC::Structure* structure)
+    {
+        JSTestNamedDeleterWithIdentifierPrototype* ptr = new (NotNull, JSC::allocateCell<JSTestNamedDeleterWithIdentifierPrototype>(vm.heap)) JSTestNamedDeleterWithIdentifierPrototype(vm, globalObject, structure);
+        ptr->finishCreation(vm);
+        return ptr;
+    }
+
+    DECLARE_INFO;
+    static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
+    {
+        return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());
+    }
+
+private:
+    JSTestNamedDeleterWithIdentifierPrototype(JSC::VM& vm, JSC::JSGlobalObject*, JSC::Structure* structure)
+        : JSC::JSNonFinalObject(vm, structure)
+    {
+    }
+
+    void finishCreation(JSC::VM&);
+};
+
+using JSTestNamedDeleterWithIdentifierConstructor = JSDOMConstructorNotConstructable<JSTestNamedDeleterWithIdentifier>;
+
+template<> JSValue JSTestNamedDeleterWithIdentifierConstructor::prototypeForStructure(JSC::VM& vm, const JSDOMGlobalObject& globalObject)
+{
+    UNUSED_PARAM(vm);
+    return globalObject.functionPrototype();
+}
+
+template<> void JSTestNamedDeleterWithIdentifierConstructor::initializeProperties(VM& vm, JSDOMGlobalObject& globalObject)
+{
+    putDirect(vm, vm.propertyNames->prototype, JSTestNamedDeleterWithIdentifier::prototype(vm, globalObject), DontDelete | ReadOnly | DontEnum);
+    putDirect(vm, vm.propertyNames->name, jsNontrivialString(&vm, String(ASCIILiteral("TestNamedDeleterWithIdentifier"))), ReadOnly | DontEnum);
+    putDirect(vm, vm.propertyNames->length, jsNumber(0), ReadOnly | DontEnum);
+}
+
+template<> const ClassInfo JSTestNamedDeleterWithIdentifierConstructor::s_info = { "TestNamedDeleterWithIdentifier", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSTestNamedDeleterWithIdentifierConstructor) };
+
+/* Hash table for prototype */
+
+static const HashTableValue JSTestNamedDeleterWithIdentifierPrototypeTableValues[] =
+{
+    { "constructor", DontEnum, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestNamedDeleterWithIdentifierConstructor), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSTestNamedDeleterWithIdentifierConstructor) } },
+    { "remove", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestNamedDeleterWithIdentifierPrototypeFunctionRemove), (intptr_t) (1) } },
+};
+
+const ClassInfo JSTestNamedDeleterWithIdentifierPrototype::s_info = { "TestNamedDeleterWithIdentifierPrototype", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSTestNamedDeleterWithIdentifierPrototype) };
+
+void JSTestNamedDeleterWithIdentifierPrototype::finishCreation(VM& vm)
+{
+    Base::finishCreation(vm);
+    reifyStaticProperties(vm, JSTestNamedDeleterWithIdentifierPrototypeTableValues, *this);
+}
+
+const ClassInfo JSTestNamedDeleterWithIdentifier::s_info = { "TestNamedDeleterWithIdentifier", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSTestNamedDeleterWithIdentifier) };
+
+JSTestNamedDeleterWithIdentifier::JSTestNamedDeleterWithIdentifier(Structure* structure, JSDOMGlobalObject& globalObject, Ref<TestNamedDeleterWithIdentifier>&& impl)
+    : JSDOMWrapper<TestNamedDeleterWithIdentifier>(structure, globalObject, WTFMove(impl))
+{
+}
+
+void JSTestNamedDeleterWithIdentifier::finishCreation(VM& vm)
+{
+    Base::finishCreation(vm);
+    ASSERT(inherits(vm, info()));
+
+}
+
+JSObject* JSTestNamedDeleterWithIdentifier::createPrototype(VM& vm, JSDOMGlobalObject& globalObject)
+{
+    return JSTestNamedDeleterWithIdentifierPrototype::create(vm, &globalObject, JSTestNamedDeleterWithIdentifierPrototype::createStructure(vm, &globalObject, globalObject.objectPrototype()));
+}
+
+JSObject* JSTestNamedDeleterWithIdentifier::prototype(VM& vm, JSDOMGlobalObject& globalObject)
+{
+    return getDOMPrototype<JSTestNamedDeleterWithIdentifier>(vm, globalObject);
+}
+
+JSValue JSTestNamedDeleterWithIdentifier::getConstructor(VM& vm, const JSGlobalObject* globalObject)
+{
+    return getDOMConstructor<JSTestNamedDeleterWithIdentifierConstructor>(vm, *jsCast<const JSDOMGlobalObject*>(globalObject));
+}
+
+void JSTestNamedDeleterWithIdentifier::destroy(JSC::JSCell* cell)
+{
+    JSTestNamedDeleterWithIdentifier* thisObject = static_cast<JSTestNamedDeleterWithIdentifier*>(cell);
+    thisObject->JSTestNamedDeleterWithIdentifier::~JSTestNamedDeleterWithIdentifier();
+}
+
+bool JSTestNamedDeleterWithIdentifier::getOwnPropertySlot(JSObject* object, ExecState* state, PropertyName propertyName, PropertySlot& slot)
+{
+    auto* thisObject = jsCast<JSTestNamedDeleterWithIdentifier*>(object);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
+    if (Base::getOwnPropertySlot(thisObject, state, propertyName, slot))
+        return true;
+    JSValue proto = thisObject->getPrototypeDirect();
+    if (proto.isObject() && jsCast<JSObject*>(proto)->hasProperty(state, propertyName))
+        return false;
+
+    if (thisObject->classInfo() == info() && !propertyName.isSymbol()) {
+        auto item = thisObject->wrapped().namedItem(propertyNameToAtomicString(propertyName));
+        if (!IDLDOMString::isNullValue(item)) {
+            slot.setValue(thisObject, ReadOnly, toJS<IDLDOMString>(*state, item));
+            return true;
+        }
+    }
+    return false;
+}
+
+bool JSTestNamedDeleterWithIdentifier::getOwnPropertySlotByIndex(JSObject* object, ExecState* state, unsigned index, PropertySlot& slot)
+{
+    auto* thisObject = jsCast<JSTestNamedDeleterWithIdentifier*>(object);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
+    Identifier propertyName = Identifier::from(state, index);
+    if (thisObject->classInfo() == info()) {
+        auto item = thisObject->wrapped().namedItem(propertyNameToAtomicString(propertyName));
+        if (!IDLDOMString::isNullValue(item)) {
+            slot.setValue(thisObject, ReadOnly, toJS<IDLDOMString>(*state, item));
+            return true;
+        }
+    }
+    return Base::getOwnPropertySlotByIndex(thisObject, state, index, slot);
+}
+
+void JSTestNamedDeleterWithIdentifier::getOwnPropertyNames(JSObject* object, ExecState* state, PropertyNameArray& propertyNames, EnumerationMode mode)
+{
+    auto* thisObject = jsCast<JSTestNamedDeleterWithIdentifier*>(object);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
+    for (auto& propertyName : thisObject->wrapped().supportedPropertyNames())
+        propertyNames.add(Identifier::fromString(state, propertyName));
+    Base::getOwnPropertyNames(thisObject, state, propertyNames, mode);
+}
+
+bool JSTestNamedDeleterWithIdentifier::deleteProperty(JSCell* cell, ExecState* state, PropertyName propertyName)
+{
+    auto& thisObject = *jsCast<JSTestNamedDeleterWithIdentifier*>(cell);
+    auto& impl = thisObject.wrapped();
+    if (isVisibleNamedProperty<false>(*state, thisObject, propertyName)) {
+        impl.remove(propertyNameToString(propertyName));
+        return true;
+    }
+    return Base::deleteProperty(cell, state, propertyName);
+}
+
+bool JSTestNamedDeleterWithIdentifier::deletePropertyByIndex(JSCell* cell, ExecState* state, unsigned index)
+{
+    auto& thisObject = *jsCast<JSTestNamedDeleterWithIdentifier*>(cell);
+    auto& impl = thisObject.wrapped();
+    auto propertyName = Identifier::from(state, index);
+    if (isVisibleNamedProperty<false>(*state, thisObject, propertyName)) {
+        impl.remove(propertyNameToString(propertyName));
+        return true;
+    }
+    return Base::deletePropertyByIndex(cell, state, index);
+}
+
+template<> inline JSTestNamedDeleterWithIdentifier* IDLOperation<JSTestNamedDeleterWithIdentifier>::cast(ExecState& state)
+{
+    return jsDynamicDowncast<JSTestNamedDeleterWithIdentifier*>(state.vm(), state.thisValue());
+}
+
+EncodedJSValue jsTestNamedDeleterWithIdentifierConstructor(ExecState* state, EncodedJSValue thisValue, PropertyName)
+{
+    VM& vm = state->vm();
+    auto throwScope = DECLARE_THROW_SCOPE(vm);
+    auto* prototype = jsDynamicDowncast<JSTestNamedDeleterWithIdentifierPrototype*>(vm, JSValue::decode(thisValue));
+    if (UNLIKELY(!prototype))
+        return throwVMTypeError(state, throwScope);
+    return JSValue::encode(JSTestNamedDeleterWithIdentifier::getConstructor(state->vm(), prototype->globalObject()));
+}
+
+bool setJSTestNamedDeleterWithIdentifierConstructor(ExecState* state, EncodedJSValue thisValue, EncodedJSValue encodedValue)
+{
+    VM& vm = state->vm();
+    auto throwScope = DECLARE_THROW_SCOPE(vm);
+    auto* prototype = jsDynamicDowncast<JSTestNamedDeleterWithIdentifierPrototype*>(vm, JSValue::decode(thisValue));
+    if (UNLIKELY(!prototype)) {
+        throwVMTypeError(state, throwScope);
+        return false;
+    }
+    // Shadowing a built-in constructor
+    return prototype->putDirect(state->vm(), state->propertyNames().constructor, JSValue::decode(encodedValue));
+}
+
+static inline JSC::EncodedJSValue jsTestNamedDeleterWithIdentifierPrototypeFunctionRemoveBody(JSC::ExecState* state, typename IDLOperation<JSTestNamedDeleterWithIdentifier>::ClassParameter 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 name = convert<IDLDOMString>(*state, state->uncheckedArgument(0));
+    RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
+    impl.remove(WTFMove(name));
+    return JSValue::encode(jsUndefined());
+}
+
+EncodedJSValue JSC_HOST_CALL jsTestNamedDeleterWithIdentifierPrototypeFunctionRemove(ExecState* state)
+{
+    return IDLOperation<JSTestNamedDeleterWithIdentifier>::call<jsTestNamedDeleterWithIdentifierPrototypeFunctionRemoveBody>(*state, "remove");
+}
+
+bool JSTestNamedDeleterWithIdentifierOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor)
+{
+    UNUSED_PARAM(handle);
+    UNUSED_PARAM(visitor);
+    return false;
+}
+
+void JSTestNamedDeleterWithIdentifierOwner::finalize(JSC::Handle<JSC::Unknown> handle, void* context)
+{
+    auto* jsTestNamedDeleterWithIdentifier = static_cast<JSTestNamedDeleterWithIdentifier*>(handle.slot()->asCell());
+    auto& world = *static_cast<DOMWrapperWorld*>(context);
+    uncacheWrapper(world, &jsTestNamedDeleterWithIdentifier->wrapped(), jsTestNamedDeleterWithIdentifier);
+}
+
+#if ENABLE(BINDING_INTEGRITY)
+#if PLATFORM(WIN)
+#pragma warning(disable: 4483)
+extern "C" { extern void (*const __identifier("??_7TestNamedDeleterWithIdentifier@WebCore@@6B@")[])(); }
+#else
+extern "C" { extern void* _ZTVN7WebCore30TestNamedDeleterWithIdentifierE[]; }
+#endif
+#endif
+
+JSC::JSValue toJSNewlyCreated(JSC::ExecState*, JSDOMGlobalObject* globalObject, Ref<TestNamedDeleterWithIdentifier>&& impl)
+{
+
+#if ENABLE(BINDING_INTEGRITY)
+    void* actualVTablePointer = *(reinterpret_cast<void**>(impl.ptr()));
+#if PLATFORM(WIN)
+    void* expectedVTablePointer = reinterpret_cast<void*>(__identifier("??_7TestNamedDeleterWithIdentifier@WebCore@@6B@"));
+#else
+    void* expectedVTablePointer = &_ZTVN7WebCore30TestNamedDeleterWithIdentifierE[2];
+#if COMPILER(CLANG)
+    // If this fails TestNamedDeleterWithIdentifier does not have a vtable, so you need to add the
+    // ImplementationLacksVTable attribute to the interface definition
+    static_assert(__is_polymorphic(TestNamedDeleterWithIdentifier), "TestNamedDeleterWithIdentifier is not polymorphic");
+#endif
+#endif
+    // If you hit this assertion you either have a use after free bug, or
+    // TestNamedDeleterWithIdentifier has subclasses. If TestNamedDeleterWithIdentifier has subclasses that get passed
+    // to toJS() we currently require TestNamedDeleterWithIdentifier you to opt out of binding hardening
+    // by adding the SkipVTableValidation attribute to the interface IDL definition
+    RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer);
+#endif
+    return createWrapper<TestNamedDeleterWithIdentifier>(globalObject, WTFMove(impl));
+}
+
+JSC::JSValue toJS(JSC::ExecState* state, JSDOMGlobalObject* globalObject, TestNamedDeleterWithIdentifier& impl)
+{
+    return wrap(state, globalObject, impl);
+}
+
+TestNamedDeleterWithIdentifier* JSTestNamedDeleterWithIdentifier::toWrapped(JSC::VM& vm, JSC::JSValue value)
+{
+    if (auto* wrapper = jsDynamicDowncast<JSTestNamedDeleterWithIdentifier*>(vm, value))
+        return &wrapper->wrapped();
+    return nullptr;
+}
+
+}
diff --git a/Source/WebCore/bindings/scripts/test/JS/JSTestNamedDeleterWithIdentifier.h b/Source/WebCore/bindings/scripts/test/JS/JSTestNamedDeleterWithIdentifier.h
new file mode 100644 (file)
index 0000000..853d683
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+    This file is part of the WebKit open source project.
+    This file has been generated by generate-bindings.pl. DO NOT MODIFY!
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#pragma once
+
+#include "JSDOMWrapper.h"
+#include "TestNamedDeleterWithIdentifier.h"
+#include <wtf/NeverDestroyed.h>
+
+namespace WebCore {
+
+class JSTestNamedDeleterWithIdentifier : public JSDOMWrapper<TestNamedDeleterWithIdentifier> {
+public:
+    using Base = JSDOMWrapper<TestNamedDeleterWithIdentifier>;
+    static JSTestNamedDeleterWithIdentifier* create(JSC::Structure* structure, JSDOMGlobalObject* globalObject, Ref<TestNamedDeleterWithIdentifier>&& impl)
+    {
+        JSTestNamedDeleterWithIdentifier* ptr = new (NotNull, JSC::allocateCell<JSTestNamedDeleterWithIdentifier>(globalObject->vm().heap)) JSTestNamedDeleterWithIdentifier(structure, *globalObject, WTFMove(impl));
+        ptr->finishCreation(globalObject->vm());
+        return ptr;
+    }
+
+    static JSC::JSObject* createPrototype(JSC::VM&, JSDOMGlobalObject&);
+    static JSC::JSObject* prototype(JSC::VM&, JSDOMGlobalObject&);
+    static TestNamedDeleterWithIdentifier* toWrapped(JSC::VM&, JSC::JSValue);
+    static bool getOwnPropertySlot(JSC::JSObject*, JSC::ExecState*, JSC::PropertyName, JSC::PropertySlot&);
+    static bool getOwnPropertySlotByIndex(JSC::JSObject*, JSC::ExecState*, unsigned propertyName, JSC::PropertySlot&);
+    static bool deleteProperty(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName);
+    static bool deletePropertyByIndex(JSC::JSCell*, JSC::ExecState*, unsigned);
+    static void destroy(JSC::JSCell*);
+
+    DECLARE_INFO;
+
+    static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
+    {
+        return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());
+    }
+
+    static void getOwnPropertyNames(JSC::JSObject*, JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode = JSC::EnumerationMode());
+    static JSC::JSValue getConstructor(JSC::VM&, const JSC::JSGlobalObject*);
+public:
+    static const unsigned StructureFlags = JSC::GetOwnPropertySlotIsImpureForPropertyAbsence | JSC::InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | JSC::OverridesGetOwnPropertySlot | JSC::OverridesGetPropertyNames | Base::StructureFlags;
+protected:
+    JSTestNamedDeleterWithIdentifier(JSC::Structure*, JSDOMGlobalObject&, Ref<TestNamedDeleterWithIdentifier>&&);
+
+    void finishCreation(JSC::VM&);
+};
+
+class JSTestNamedDeleterWithIdentifierOwner : public JSC::WeakHandleOwner {
+public:
+    virtual bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown>, void* context, JSC::SlotVisitor&);
+    virtual void finalize(JSC::Handle<JSC::Unknown>, void* context);
+};
+
+inline JSC::WeakHandleOwner* wrapperOwner(DOMWrapperWorld&, TestNamedDeleterWithIdentifier*)
+{
+    static NeverDestroyed<JSTestNamedDeleterWithIdentifierOwner> owner;
+    return &owner.get();
+}
+
+inline void* wrapperKey(TestNamedDeleterWithIdentifier* wrappableObject)
+{
+    return wrappableObject;
+}
+
+JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, TestNamedDeleterWithIdentifier&);
+inline JSC::JSValue toJS(JSC::ExecState* state, JSDOMGlobalObject* globalObject, TestNamedDeleterWithIdentifier* impl) { return impl ? toJS(state, globalObject, *impl) : JSC::jsNull(); }
+JSC::JSValue toJSNewlyCreated(JSC::ExecState*, JSDOMGlobalObject*, Ref<TestNamedDeleterWithIdentifier>&&);
+inline JSC::JSValue toJSNewlyCreated(JSC::ExecState* state, JSDOMGlobalObject* globalObject, RefPtr<TestNamedDeleterWithIdentifier>&& impl) { return impl ? toJSNewlyCreated(state, globalObject, impl.releaseNonNull()) : JSC::jsNull(); }
+
+template<> struct JSDOMWrapperConverterTraits<TestNamedDeleterWithIdentifier> {
+    using WrapperClass = JSTestNamedDeleterWithIdentifier;
+    using ToWrappedReturnType = TestNamedDeleterWithIdentifier*;
+};
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/scripts/test/JS/JSTestNamedDeleterWithIndexedGetter.cpp b/Source/WebCore/bindings/scripts/test/JS/JSTestNamedDeleterWithIndexedGetter.cpp
new file mode 100644 (file)
index 0000000..d40802d
--- /dev/null
@@ -0,0 +1,285 @@
+/*
+    This file is part of the WebKit open source project.
+    This file has been generated by generate-bindings.pl. DO NOT MODIFY!
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+#include "JSTestNamedDeleterWithIndexedGetter.h"
+
+#include "JSDOMAbstractOperations.h"
+#include "JSDOMBinding.h"
+#include "JSDOMConstructorNotConstructable.h"
+#include "JSDOMConvert.h"
+#include "JSDOMExceptionHandling.h"
+#include "JSDOMWrapperCache.h"
+#include "URL.h"
+#include <runtime/FunctionPrototype.h>
+#include <runtime/PropertyNameArray.h>
+#include <wtf/GetPtr.h>
+
+using namespace JSC;
+
+namespace WebCore {
+
+// Attributes
+
+JSC::EncodedJSValue jsTestNamedDeleterWithIndexedGetterConstructor(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
+bool setJSTestNamedDeleterWithIndexedGetterConstructor(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);
+
+class JSTestNamedDeleterWithIndexedGetterPrototype : public JSC::JSNonFinalObject {
+public:
+    using Base = JSC::JSNonFinalObject;
+    static JSTestNamedDeleterWithIndexedGetterPrototype* create(JSC::VM& vm, JSDOMGlobalObject* globalObject, JSC::Structure* structure)
+    {
+        JSTestNamedDeleterWithIndexedGetterPrototype* ptr = new (NotNull, JSC::allocateCell<JSTestNamedDeleterWithIndexedGetterPrototype>(vm.heap)) JSTestNamedDeleterWithIndexedGetterPrototype(vm, globalObject, structure);
+        ptr->finishCreation(vm);
+        return ptr;
+    }
+
+    DECLARE_INFO;
+    static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
+    {
+        return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());
+    }
+
+private:
+    JSTestNamedDeleterWithIndexedGetterPrototype(JSC::VM& vm, JSC::JSGlobalObject*, JSC::Structure* structure)
+        : JSC::JSNonFinalObject(vm, structure)
+    {
+    }
+
+    void finishCreation(JSC::VM&);
+};
+
+using JSTestNamedDeleterWithIndexedGetterConstructor = JSDOMConstructorNotConstructable<JSTestNamedDeleterWithIndexedGetter>;
+
+template<> JSValue JSTestNamedDeleterWithIndexedGetterConstructor::prototypeForStructure(JSC::VM& vm, const JSDOMGlobalObject& globalObject)
+{
+    UNUSED_PARAM(vm);
+    return globalObject.functionPrototype();
+}
+
+template<> void JSTestNamedDeleterWithIndexedGetterConstructor::initializeProperties(VM& vm, JSDOMGlobalObject& globalObject)
+{
+    putDirect(vm, vm.propertyNames->prototype, JSTestNamedDeleterWithIndexedGetter::prototype(vm, globalObject), DontDelete | ReadOnly | DontEnum);
+    putDirect(vm, vm.propertyNames->name, jsNontrivialString(&vm, String(ASCIILiteral("TestNamedDeleterWithIndexedGetter"))), ReadOnly | DontEnum);
+    putDirect(vm, vm.propertyNames->length, jsNumber(0), ReadOnly | DontEnum);
+}
+
+template<> const ClassInfo JSTestNamedDeleterWithIndexedGetterConstructor::s_info = { "TestNamedDeleterWithIndexedGetter", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSTestNamedDeleterWithIndexedGetterConstructor) };
+
+/* Hash table for prototype */
+
+static const HashTableValue JSTestNamedDeleterWithIndexedGetterPrototypeTableValues[] =
+{
+    { "constructor", DontEnum, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestNamedDeleterWithIndexedGetterConstructor), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSTestNamedDeleterWithIndexedGetterConstructor) } },
+};
+
+const ClassInfo JSTestNamedDeleterWithIndexedGetterPrototype::s_info = { "TestNamedDeleterWithIndexedGetterPrototype", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSTestNamedDeleterWithIndexedGetterPrototype) };
+
+void JSTestNamedDeleterWithIndexedGetterPrototype::finishCreation(VM& vm)
+{
+    Base::finishCreation(vm);
+    reifyStaticProperties(vm, JSTestNamedDeleterWithIndexedGetterPrototypeTableValues, *this);
+}
+
+const ClassInfo JSTestNamedDeleterWithIndexedGetter::s_info = { "TestNamedDeleterWithIndexedGetter", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSTestNamedDeleterWithIndexedGetter) };
+
+JSTestNamedDeleterWithIndexedGetter::JSTestNamedDeleterWithIndexedGetter(Structure* structure, JSDOMGlobalObject& globalObject, Ref<TestNamedDeleterWithIndexedGetter>&& impl)
+    : JSDOMWrapper<TestNamedDeleterWithIndexedGetter>(structure, globalObject, WTFMove(impl))
+{
+}
+
+void JSTestNamedDeleterWithIndexedGetter::finishCreation(VM& vm)
+{
+    Base::finishCreation(vm);
+    ASSERT(inherits(vm, info()));
+
+}
+
+JSObject* JSTestNamedDeleterWithIndexedGetter::createPrototype(VM& vm, JSDOMGlobalObject& globalObject)
+{
+    return JSTestNamedDeleterWithIndexedGetterPrototype::create(vm, &globalObject, JSTestNamedDeleterWithIndexedGetterPrototype::createStructure(vm, &globalObject, globalObject.objectPrototype()));
+}
+
+JSObject* JSTestNamedDeleterWithIndexedGetter::prototype(VM& vm, JSDOMGlobalObject& globalObject)
+{
+    return getDOMPrototype<JSTestNamedDeleterWithIndexedGetter>(vm, globalObject);
+}
+
+JSValue JSTestNamedDeleterWithIndexedGetter::getConstructor(VM& vm, const JSGlobalObject* globalObject)
+{
+    return getDOMConstructor<JSTestNamedDeleterWithIndexedGetterConstructor>(vm, *jsCast<const JSDOMGlobalObject*>(globalObject));
+}
+
+void JSTestNamedDeleterWithIndexedGetter::destroy(JSC::JSCell* cell)
+{
+    JSTestNamedDeleterWithIndexedGetter* thisObject = static_cast<JSTestNamedDeleterWithIndexedGetter*>(cell);
+    thisObject->JSTestNamedDeleterWithIndexedGetter::~JSTestNamedDeleterWithIndexedGetter();
+}
+
+bool JSTestNamedDeleterWithIndexedGetter::getOwnPropertySlot(JSObject* object, ExecState* state, PropertyName propertyName, PropertySlot& slot)
+{
+    auto* thisObject = jsCast<JSTestNamedDeleterWithIndexedGetter*>(object);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
+    auto optionalIndex = parseIndex(propertyName);
+    if (optionalIndex && optionalIndex.value() < thisObject->wrapped().length()) {
+        auto index = optionalIndex.value();
+        slot.setValue(thisObject, ReadOnly, toJS<IDLDOMString>(*state, thisObject->wrapped().item(index)));
+        return true;
+    }
+    if (Base::getOwnPropertySlot(thisObject, state, propertyName, slot))
+        return true;
+    JSValue proto = thisObject->getPrototypeDirect();
+    if (proto.isObject() && jsCast<JSObject*>(proto)->hasProperty(state, propertyName))
+        return false;
+
+    if (!optionalIndex && thisObject->classInfo() == info() && !propertyName.isSymbol()) {
+        auto item = thisObject->wrapped().namedItem(propertyNameToAtomicString(propertyName));
+        if (!IDLDOMString::isNullValue(item)) {
+            slot.setValue(thisObject, ReadOnly, toJS<IDLDOMString>(*state, item));
+            return true;
+        }
+    }
+    return false;
+}
+
+bool JSTestNamedDeleterWithIndexedGetter::getOwnPropertySlotByIndex(JSObject* object, ExecState* state, unsigned index, PropertySlot& slot)
+{
+    auto* thisObject = jsCast<JSTestNamedDeleterWithIndexedGetter*>(object);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
+    if (LIKELY(index < thisObject->wrapped().length())) {
+        slot.setValue(thisObject, ReadOnly, toJS<IDLDOMString>(*state, thisObject->wrapped().item(index)));
+        return true;
+    }
+    return Base::getOwnPropertySlotByIndex(thisObject, state, index, slot);
+}
+
+void JSTestNamedDeleterWithIndexedGetter::getOwnPropertyNames(JSObject* object, ExecState* state, PropertyNameArray& propertyNames, EnumerationMode mode)
+{
+    auto* thisObject = jsCast<JSTestNamedDeleterWithIndexedGetter*>(object);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
+    for (unsigned i = 0, count = thisObject->wrapped().length(); i < count; ++i)
+        propertyNames.add(Identifier::from(state, i));
+    for (auto& propertyName : thisObject->wrapped().supportedPropertyNames())
+        propertyNames.add(Identifier::fromString(state, propertyName));
+    Base::getOwnPropertyNames(thisObject, state, propertyNames, mode);
+}
+
+bool JSTestNamedDeleterWithIndexedGetter::deleteProperty(JSCell* cell, ExecState* state, PropertyName propertyName)
+{
+    auto& thisObject = *jsCast<JSTestNamedDeleterWithIndexedGetter*>(cell);
+    auto& impl = thisObject.wrapped();
+    if (auto index = parseIndex(propertyName))
+        return !impl.isSupportedPropertyIndex(index.value()) ? true : false;
+    if (isVisibleNamedProperty<false>(*state, thisObject, propertyName)) {
+        return impl.deleteNamedProperty(propertyNameToString(propertyName));
+    }
+    return Base::deleteProperty(cell, state, propertyName);
+}
+
+bool JSTestNamedDeleterWithIndexedGetter::deletePropertyByIndex(JSCell* cell, ExecState* state, unsigned index)
+{
+    auto& thisObject = *jsCast<JSTestNamedDeleterWithIndexedGetter*>(cell);
+    auto& impl = thisObject.wrapped();
+    return !impl.isSupportedPropertyIndex(index) ? true : false;
+}
+
+EncodedJSValue jsTestNamedDeleterWithIndexedGetterConstructor(ExecState* state, EncodedJSValue thisValue, PropertyName)
+{
+    VM& vm = state->vm();
+    auto throwScope = DECLARE_THROW_SCOPE(vm);
+    auto* prototype = jsDynamicDowncast<JSTestNamedDeleterWithIndexedGetterPrototype*>(vm, JSValue::decode(thisValue));
+    if (UNLIKELY(!prototype))
+        return throwVMTypeError(state, throwScope);
+    return JSValue::encode(JSTestNamedDeleterWithIndexedGetter::getConstructor(state->vm(), prototype->globalObject()));
+}
+
+bool setJSTestNamedDeleterWithIndexedGetterConstructor(ExecState* state, EncodedJSValue thisValue, EncodedJSValue encodedValue)
+{
+    VM& vm = state->vm();
+    auto throwScope = DECLARE_THROW_SCOPE(vm);
+    auto* prototype = jsDynamicDowncast<JSTestNamedDeleterWithIndexedGetterPrototype*>(vm, JSValue::decode(thisValue));
+    if (UNLIKELY(!prototype)) {
+        throwVMTypeError(state, throwScope);
+        return false;
+    }
+    // Shadowing a built-in constructor
+    return prototype->putDirect(state->vm(), state->propertyNames().constructor, JSValue::decode(encodedValue));
+}
+
+bool JSTestNamedDeleterWithIndexedGetterOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor)
+{
+    UNUSED_PARAM(handle);
+    UNUSED_PARAM(visitor);
+    return false;
+}
+
+void JSTestNamedDeleterWithIndexedGetterOwner::finalize(JSC::Handle<JSC::Unknown> handle, void* context)
+{
+    auto* jsTestNamedDeleterWithIndexedGetter = static_cast<JSTestNamedDeleterWithIndexedGetter*>(handle.slot()->asCell());
+    auto& world = *static_cast<DOMWrapperWorld*>(context);
+    uncacheWrapper(world, &jsTestNamedDeleterWithIndexedGetter->wrapped(), jsTestNamedDeleterWithIndexedGetter);
+}
+
+#if ENABLE(BINDING_INTEGRITY)
+#if PLATFORM(WIN)
+#pragma warning(disable: 4483)
+extern "C" { extern void (*const __identifier("??_7TestNamedDeleterWithIndexedGetter@WebCore@@6B@")[])(); }
+#else
+extern "C" { extern void* _ZTVN7WebCore33TestNamedDeleterWithIndexedGetterE[]; }
+#endif
+#endif
+
+JSC::JSValue toJSNewlyCreated(JSC::ExecState*, JSDOMGlobalObject* globalObject, Ref<TestNamedDeleterWithIndexedGetter>&& impl)
+{
+
+#if ENABLE(BINDING_INTEGRITY)
+    void* actualVTablePointer = *(reinterpret_cast<void**>(impl.ptr()));
+#if PLATFORM(WIN)
+    void* expectedVTablePointer = reinterpret_cast<void*>(__identifier("??_7TestNamedDeleterWithIndexedGetter@WebCore@@6B@"));
+#else
+    void* expectedVTablePointer = &_ZTVN7WebCore33TestNamedDeleterWithIndexedGetterE[2];
+#if COMPILER(CLANG)
+    // If this fails TestNamedDeleterWithIndexedGetter does not have a vtable, so you need to add the
+    // ImplementationLacksVTable attribute to the interface definition
+    static_assert(__is_polymorphic(TestNamedDeleterWithIndexedGetter), "TestNamedDeleterWithIndexedGetter is not polymorphic");
+#endif
+#endif
+    // If you hit this assertion you either have a use after free bug, or
+    // TestNamedDeleterWithIndexedGetter has subclasses. If TestNamedDeleterWithIndexedGetter has subclasses that get passed
+    // to toJS() we currently require TestNamedDeleterWithIndexedGetter you to opt out of binding hardening
+    // by adding the SkipVTableValidation attribute to the interface IDL definition
+    RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer);
+#endif
+    return createWrapper<TestNamedDeleterWithIndexedGetter>(globalObject, WTFMove(impl));
+}
+
+JSC::JSValue toJS(JSC::ExecState* state, JSDOMGlobalObject* globalObject, TestNamedDeleterWithIndexedGetter& impl)
+{
+    return wrap(state, globalObject, impl);
+}
+
+TestNamedDeleterWithIndexedGetter* JSTestNamedDeleterWithIndexedGetter::toWrapped(JSC::VM& vm, JSC::JSValue value)
+{
+    if (auto* wrapper = jsDynamicDowncast<JSTestNamedDeleterWithIndexedGetter*>(vm, value))
+        return &wrapper->wrapped();
+    return nullptr;
+}
+
+}
diff --git a/Source/WebCore/bindings/scripts/test/JS/JSTestNamedDeleterWithIndexedGetter.h b/Source/WebCore/bindings/scripts/test/JS/JSTestNamedDeleterWithIndexedGetter.h
new file mode 100644 (file)
index 0000000..cd84d7b
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+    This file is part of the WebKit open source project.
+    This file has been generated by generate-bindings.pl. DO NOT MODIFY!
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#pragma once
+
+#include "JSDOMWrapper.h"
+#include "TestNamedDeleterWithIndexedGetter.h"
+#include <wtf/NeverDestroyed.h>
+
+namespace WebCore {
+
+class JSTestNamedDeleterWithIndexedGetter : public JSDOMWrapper<TestNamedDeleterWithIndexedGetter> {
+public:
+    using Base = JSDOMWrapper<TestNamedDeleterWithIndexedGetter>;
+    static JSTestNamedDeleterWithIndexedGetter* create(JSC::Structure* structure, JSDOMGlobalObject* globalObject, Ref<TestNamedDeleterWithIndexedGetter>&& impl)
+    {
+        JSTestNamedDeleterWithIndexedGetter* ptr = new (NotNull, JSC::allocateCell<JSTestNamedDeleterWithIndexedGetter>(globalObject->vm().heap)) JSTestNamedDeleterWithIndexedGetter(structure, *globalObject, WTFMove(impl));
+        ptr->finishCreation(globalObject->vm());
+        return ptr;
+    }
+
+    static JSC::JSObject* createPrototype(JSC::VM&, JSDOMGlobalObject&);
+    static JSC::JSObject* prototype(JSC::VM&, JSDOMGlobalObject&);
+    static TestNamedDeleterWithIndexedGetter* toWrapped(JSC::VM&, JSC::JSValue);
+    static bool getOwnPropertySlot(JSC::JSObject*, JSC::ExecState*, JSC::PropertyName, JSC::PropertySlot&);
+    static bool getOwnPropertySlotByIndex(JSC::JSObject*, JSC::ExecState*, unsigned propertyName, JSC::PropertySlot&);
+    static bool deleteProperty(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName);
+    static bool deletePropertyByIndex(JSC::JSCell*, JSC::ExecState*, unsigned);
+    static void destroy(JSC::JSCell*);
+
+    DECLARE_INFO;
+
+    static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
+    {
+        return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());
+    }
+
+    static void getOwnPropertyNames(JSC::JSObject*, JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode = JSC::EnumerationMode());
+    static JSC::JSValue getConstructor(JSC::VM&, const JSC::JSGlobalObject*);
+public:
+    static const unsigned StructureFlags = JSC::GetOwnPropertySlotIsImpureForPropertyAbsence | JSC::InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | JSC::OverridesGetOwnPropertySlot | JSC::OverridesGetPropertyNames | Base::StructureFlags;
+protected:
+    JSTestNamedDeleterWithIndexedGetter(JSC::Structure*, JSDOMGlobalObject&, Ref<TestNamedDeleterWithIndexedGetter>&&);
+
+    void finishCreation(JSC::VM&);
+};
+
+class JSTestNamedDeleterWithIndexedGetterOwner : public JSC::WeakHandleOwner {
+public:
+    virtual bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown>, void* context, JSC::SlotVisitor&);
+    virtual void finalize(JSC::Handle<JSC::Unknown>, void* context);
+};
+
+inline JSC::WeakHandleOwner* wrapperOwner(DOMWrapperWorld&, TestNamedDeleterWithIndexedGetter*)
+{
+    static NeverDestroyed<JSTestNamedDeleterWithIndexedGetterOwner> owner;
+    return &owner.get();
+}
+
+inline void* wrapperKey(TestNamedDeleterWithIndexedGetter* wrappableObject)
+{
+    return wrappableObject;
+}
+
+JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, TestNamedDeleterWithIndexedGetter&);
+inline JSC::JSValue toJS(JSC::ExecState* state, JSDOMGlobalObject* globalObject, TestNamedDeleterWithIndexedGetter* impl) { return impl ? toJS(state, globalObject, *impl) : JSC::jsNull(); }
+JSC::JSValue toJSNewlyCreated(JSC::ExecState*, JSDOMGlobalObject*, Ref<TestNamedDeleterWithIndexedGetter>&&);
+inline JSC::JSValue toJSNewlyCreated(JSC::ExecState* state, JSDOMGlobalObject* globalObject, RefPtr<TestNamedDeleterWithIndexedGetter>&& impl) { return impl ? toJSNewlyCreated(state, globalObject, impl.releaseNonNull()) : JSC::jsNull(); }
+
+template<> struct JSDOMWrapperConverterTraits<TestNamedDeleterWithIndexedGetter> {
+    using WrapperClass = JSTestNamedDeleterWithIndexedGetter;
+    using ToWrappedReturnType = TestNamedDeleterWithIndexedGetter*;
+};
+
+} // namespace WebCore
index 2b4c226..3d960d9 100644 (file)
@@ -43,6 +43,8 @@ public:
     static TestObj* toWrapped(JSC::VM&, JSC::JSValue);
     static bool getOwnPropertySlot(JSC::JSObject*, JSC::ExecState*, JSC::PropertyName, JSC::PropertySlot&);
     static bool getOwnPropertySlotByIndex(JSC::JSObject*, JSC::ExecState*, unsigned propertyName, JSC::PropertySlot&);
+    static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&);
+
     static void destroy(JSC::JSCell*);
 
     DECLARE_INFO;
@@ -52,8 +54,6 @@ 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&);
diff --git a/Source/WebCore/bindings/scripts/test/TestNamedDeleterNoIdentifier.idl b/Source/WebCore/bindings/scripts/test/TestNamedDeleterNoIdentifier.idl
new file mode 100644 (file)
index 0000000..6c42227
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 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
+ * 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. AND ITS CONTRIBUTORS ``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 ITS 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.
+ */
+
+interface TestNamedDeleterNoIdentifier {
+    deleter void (DOMString name);
+
+    // NOTE: Named deleters require the presence of a named getter as well.
+    getter DOMString (DOMString name);
+};
diff --git a/Source/WebCore/bindings/scripts/test/TestNamedDeleterThrowingException.idl b/Source/WebCore/bindings/scripts/test/TestNamedDeleterThrowingException.idl
new file mode 100644 (file)
index 0000000..0501e04
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 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
+ * 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. AND ITS CONTRIBUTORS ``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 ITS 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.
+ */
+
+interface TestNamedDeleterThrowingException {
+    [MayThrowException] deleter void (DOMString name);
+
+    // NOTE: Named deleters require the presence of a named getter as well.
+    getter DOMString (DOMString name);
+};
diff --git a/Source/WebCore/bindings/scripts/test/TestNamedDeleterWithIdentifier.idl b/Source/WebCore/bindings/scripts/test/TestNamedDeleterWithIdentifier.idl
new file mode 100644 (file)
index 0000000..b41bdf4
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 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
+ * 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. AND ITS CONTRIBUTORS ``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 ITS 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.
+ */
+
+interface TestNamedDeleterWithIdentifier {
+    deleter void remove(DOMString name);
+
+    // NOTE: Named deleters require the presence of a named getter as well.
+    getter DOMString (DOMString name);
+};
diff --git a/Source/WebCore/bindings/scripts/test/TestNamedDeleterWithIndexedGetter.idl b/Source/WebCore/bindings/scripts/test/TestNamedDeleterWithIndexedGetter.idl
new file mode 100644 (file)
index 0000000..f2ecf85
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 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
+ * 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. AND ITS CONTRIBUTORS ``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 ITS 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.
+ */
+
+interface TestNamedDeleterWithIndexedGetter {
+    deleter void (DOMString name);
+
+    // The presence of an index getter changes adds additional
+    // checks to the delete algorithm.
+    getter DOMString (unsigned long index);
+
+    // NOTE: Named deleters require the presence of a named getter as well.
+    getter DOMString (DOMString name);
+};
index 34cc2d7..b318ec1 100644 (file)
 
 namespace WebCore {
 
-static ExceptionOr<Vector<uint8_t>> signRSA_PSS(CryptoAlgorithmIdentifier hash, const PlatformRSAKey key, size_t keyLength, const Vector<uint8_t>& data, size_t saltLength)
+static ExceptionOr<Vector<uint8_t>> signRSA_PSS(CryptoAlgorithmIdentifier, const PlatformRSAKey, size_t, const Vector<uint8_t>&, size_t)
 {
-    CCDigestAlgorithm digestAlgorithm;
-    if (!getCommonCryptoDigestAlgorithm(hash, digestAlgorithm))
+    // CCDigestAlgorithm digestAlgorithm;
+    // if (!getCommonCryptoDigestAlgorithm(hash, digestAlgorithm))
+    //     return Exception { OperationError };
+    // 
+    // auto cryptoDigestAlgorithm = WebCore::cryptoDigestAlgorithm(hash);
+    // if (!cryptoDigestAlgorithm)
+    //     return Exception { OperationError };
+    // auto digest = PAL::CryptoDigest::create(*cryptoDigestAlgorithm);
+    // if (!digest)
+    //     return Exception { OperationError };
+    // digest->addBytes(data.data(), data.size());
+    // auto digestData = digest->computeHash();
+    // 
+    // Vector<uint8_t> signature(keyLength / 8); // Per https://tools.ietf.org/html/rfc3447#section-8.1.1
+    // size_t signatureSize = signature.size();
+    // 
+    // CCCryptorStatus status = CCRSACryptorSign(key, ccRSAPSSPadding, digestData.data(), digestData.size(), digestAlgorithm, saltLength, signature.data(), &signatureSize);
+    // if (status)
         return Exception { OperationError };
 
-    auto cryptoDigestAlgorithm = WebCore::cryptoDigestAlgorithm(hash);
-    if (!cryptoDigestAlgorithm)
-        return Exception { OperationError };
-    auto digest = PAL::CryptoDigest::create(*cryptoDigestAlgorithm);
-    if (!digest)
-        return Exception { OperationError };
-    digest->addBytes(data.data(), data.size());
-    auto digestData = digest->computeHash();
-
-    Vector<uint8_t> signature(keyLength / 8); // Per https://tools.ietf.org/html/rfc3447#section-8.1.1
-    size_t signatureSize = signature.size();
-
-    CCCryptorStatus status = CCRSACryptorSign(key, ccRSAPSSPadding, digestData.data(), digestData.size(), digestAlgorithm, saltLength, signature.data(), &signatureSize);
-    if (status)
-        return Exception { OperationError };
-
-    return WTFMove(signature);
+    // return WTFMove(signature);
 }
 
-static ExceptionOr<bool> verifyRSA_PSS(CryptoAlgorithmIdentifier hash, const PlatformRSAKey key, const Vector<uint8_t>& signature, const Vector<uint8_t>& data, size_t saltLength)
+static ExceptionOr<bool> verifyRSA_PSS(CryptoAlgorithmIdentifier, const PlatformRSAKey, const Vector<uint8_t>&, const Vector<uint8_t>&, size_t)
 {
-    CCDigestAlgorithm digestAlgorithm;
-    if (!getCommonCryptoDigestAlgorithm(hash, digestAlgorithm))
-        return Exception { OperationError };
-
-    auto cryptoDigestAlgorithm = WebCore::cryptoDigestAlgorithm(hash);
-    if (!cryptoDigestAlgorithm)
-        return Exception { OperationError };
-    auto digest = PAL::CryptoDigest::create(*cryptoDigestAlgorithm);
-    if (!digest)
-        return Exception { OperationError };
-    digest->addBytes(data.data(), data.size());
-    auto digestData = digest->computeHash();
-
-    auto status = CCRSACryptorVerify(key, ccRSAPSSPadding, digestData.data(), digestData.size(), digestAlgorithm, saltLength, signature.data(), signature.size());
-    if (!status)
-        return true;
+    // CCDigestAlgorithm digestAlgorithm;
+    // if (!getCommonCryptoDigestAlgorithm(hash, digestAlgorithm))
+    //     return Exception { OperationError };
+    // 
+    // auto cryptoDigestAlgorithm = WebCore::cryptoDigestAlgorithm(hash);
+    // if (!cryptoDigestAlgorithm)
+    //     return Exception { OperationError };
+    // auto digest = PAL::CryptoDigest::create(*cryptoDigestAlgorithm);
+    // if (!digest)
+    //     return Exception { OperationError };
+    // digest->addBytes(data.data(), data.size());
+    // auto digestData = digest->computeHash();
+    // 
+    // auto status = CCRSACryptorVerify(key, ccRSAPSSPadding, digestData.data(), digestData.size(), digestAlgorithm, saltLength, signature.data(), signature.size());
+    // if (!status)
+    //     return true;
     return false;
 }
 
index 4e180e7..b63e36c 100644 (file)
@@ -33,7 +33,7 @@
 
 namespace WebCore {
 
-static std::optional<PAL::CryptoDigest::Algorithm> cryptoDigestAlgorithm(CryptoAlgorithmIdentifier hashFunction)
+inline std::optional<PAL::CryptoDigest::Algorithm> cryptoDigestAlgorithm(CryptoAlgorithmIdentifier hashFunction)
 {
     switch (hashFunction) {
     case CryptoAlgorithmIdentifier::SHA_1:
index cbfa3fd..b65be3a 100644 (file)
  */
 
 [
-    GenerateIsReachable=ImplElementRoot,
-    CustomDeleteProperty,
     CustomNamedSetter,
+    GenerateIsReachable=ImplElementRoot,
     OverrideBuiltins,
     SkipVTableValidation,
 ] interface DOMStringMap {
     getter DOMString (DOMString name);
 
-    // FIXME: Add support for the setter and deleter specials.
+    // FIXME: Add support for the named setter special.
     // [CEReactions] setter void (DOMString name, DOMString value);
-    // [CEReactions] deleter void (DOMString name);
+
+    [CEReactions] deleter void (DOMString name);
 };
 
index 5f01ecf..c724ef9 100644 (file)
@@ -151,15 +151,39 @@ void DatasetDOMStringMap::deref()
     m_element.deref();
 }
 
+bool DatasetDOMStringMap::isSupportedPropertyName(const String& propertyName) const
+{
+    if (!m_element.hasAttributes())
+        return false;
+
+    auto attributeIteratorAccessor = m_element.attributesIterator();
+    if (attributeIteratorAccessor.attributeCount() == 1) {
+        // If the node has a single attribute, it is the dataset member accessed in most cases.
+        // Building a new AtomicString in that case is overkill so we do a direct character comparison.
+        const auto& attribute = *attributeIteratorAccessor.begin();
+        if (propertyNameMatchesAttributeName(propertyName, attribute.localName()))
+            return true;
+    } else {
+        auto attributeName = convertPropertyNameToAttributeName(propertyName);
+        for (const Attribute& attribute : attributeIteratorAccessor) {
+            if (attribute.localName() == attributeName)
+                return true;
+        }
+    }
+    
+    return false;
+}
+
 Vector<String> DatasetDOMStringMap::supportedPropertyNames() const
 {
     Vector<String> names;
 
-    if (m_element.hasAttributes()) {
-        for (auto& attribute : m_element.attributesIterator()) {
-            if (isValidAttributeName(attribute.localName()))
-                names.append(convertAttributeNameToPropertyName(attribute.localName()));
-        }
+    if (!m_element.hasAttributes())
+        return names;
+
+    for (auto& attribute : m_element.attributesIterator()) {
+        if (isValidAttributeName(attribute.localName()))
+            names.append(convertAttributeNameToPropertyName(attribute.localName()));
     }
 
     return names;
@@ -200,7 +224,7 @@ ExceptionOr<void> DatasetDOMStringMap::setItem(const String& name, const String&
     return m_element.setAttribute(convertPropertyNameToAttributeName(name), value);
 }
 
-bool DatasetDOMStringMap::deleteItem(const String& name)
+bool DatasetDOMStringMap::deleteNamedProperty(const String& name)
 {
     return m_element.removeAttribute(convertPropertyNameToAttributeName(name));
 }
index a3914fd..d73530e 100644 (file)
@@ -43,11 +43,12 @@ public:
     void ref();
     void deref();
 
+    bool isSupportedPropertyName(const String& name) const;
     Vector<String> supportedPropertyNames() const;
 
     String namedItem(const AtomicString& name) const;
     ExceptionOr<void> setItem(const String& name, const String& value);
-    bool deleteItem(const String& name);
+    bool deleteNamedProperty(const String& name);
 
     Element& element() { return m_element; }
 
index d10a625..bff5e59 100644 (file)
@@ -879,7 +879,7 @@ ExceptionOr<Storage*> DOMWindow::sessionStorage() const
 
     if (m_sessionStorage) {
         if (!m_sessionStorage->area().canAccessStorage(m_frame))
-        return Exception { SECURITY_ERR };
+            return Exception { SECURITY_ERR };
         return m_sessionStorage.get();
     }
 
index 11f919a..f4ceb96 100644 (file)
@@ -120,4 +120,12 @@ ExceptionOr<bool> Storage::contains(const String& key) const
     return m_storageArea->contains(key);
 }
 
+bool Storage::isSupportedPropertyName(const String& propertyName) const
+{
+    if (!m_storageArea->canAccessStorage(m_frame))
+        return false;
+
+    return m_storageArea->contains(propertyName);
+}
+
 } // namespace WebCore
index 5df3ae9..8de44fa 100644 (file)
@@ -47,13 +47,14 @@ public:
     ExceptionOr<void> clear();
     ExceptionOr<bool> contains(const String& key) const;
 
+    // Bindings support functions.
+    bool isSupportedPropertyName(const String&) const;
+
     StorageArea& area() const { return *m_storageArea; }
 
 private:
     Storage(Frame*, RefPtr<StorageArea>&&);
 
-    bool isDisabledByPrivateBrowsing() const;
-
     const RefPtr<StorageArea> m_storageArea;
 };
 
index 3d4aa56..ba88467 100644 (file)
  */
 
 [
-    GenerateIsReachable=ImplFrame,
-    CustomDeleteProperty,
     CustomEnumerateProperty,
     CustomNamedSetter,
+    GenerateIsReachable=ImplFrame,
     SkipVTableValidation,
 ] interface Storage {
     [GetterMayThrowException] readonly attribute unsigned long length;
     [MayThrowException] DOMString? key(unsigned long index);
     [MayThrowException] getter DOMString? getItem(DOMString key);
-    [MayThrowException] void setItem(DOMString key, DOMString data);
-    [MayThrowException] void removeItem(DOMString key);
+    [MayThrowException] /*setter*/ void setItem(DOMString key, DOMString data);
+    [MayThrowException] deleter void removeItem(DOMString key);
     [MayThrowException] void clear();
 };