Title: [274528] trunk
Revision
274528
Author
shvaikal...@gmail.com
Date
2021-03-16 16:00:57 -0700 (Tue, 16 Mar 2021)

Log Message

Cache cross-origin methods / accessors of Window and Location per lexical global object
https://bugs.webkit.org/show_bug.cgi?id=222739

Reviewed by Darin Adler.

LayoutTests/imported/w3c:

* web-platform-tests/html/browsers/origin/cross-origin-objects/cross-origin-objects-function-caching-expected.txt: Added.
* web-platform-tests/html/browsers/origin/cross-origin-objects/cross-origin-objects-function-caching.html: Added.
* web-platform-tests/html/browsers/origin/cross-origin-objects/cross-origin-objects-function-common.js: Added.
* web-platform-tests/html/browsers/origin/cross-origin-objects/cross-origin-objects-function-length-expected.txt: Added.
* web-platform-tests/html/browsers/origin/cross-origin-objects/cross-origin-objects-function-length.html: Added.
* web-platform-tests/html/browsers/origin/cross-origin-objects/cross-origin-objects-function-name-expected.txt: Added.
* web-platform-tests/html/browsers/origin/cross-origin-objects/cross-origin-objects-function-name.html: Added.

Source/_javascript_Core:

1. Introduce WeakGCMap::ensureValue() to clean up JSObject::getOwnPropertyDescriptor() and
   avoid double hashing. It decorates HashMap::ensure() to guarantee non-null return value.
2. Assert early that JSCustom{Getter,Setter}Function is created with non-null function pointer.
3. Rename getCustom{Getter,Setter}Function() to align with newly-added JSDOMGlobalObject methods.

* runtime/JSCustomGetterFunction.cpp:
(JSC::JSC_DEFINE_HOST_FUNCTION):
(JSC::JSCustomGetterFunction::create):
* runtime/JSCustomSetterFunction.cpp:
(JSC::JSC_DEFINE_HOST_FUNCTION):
(JSC::JSCustomSetterFunction::create):
* runtime/JSObject.cpp:
(JSC::createCustomGetterFunction):
(JSC::createCustomSetterFunction):
(JSC::JSObject::getOwnPropertyDescriptor):
(JSC::getCustomGetterFunction): Deleted.
(JSC::getCustomSetterFunction): Deleted.
* runtime/Lookup.h:
(JSC::nonCachingStaticFunctionGetterImpl): Deleted.
* runtime/WeakGCMap.h:

Source/WebCore:

For cross-origin methods / accessors, Window and Location objects return different JSFunction
instances on every [[Get]]. The intent was to ensure isolation by supplying different Realms with
different function objects. However, within the same callee Realm, this makes subsequent lookups
of a cross-origin method / accessor fail reference equality test, which is rather confusing:

    `crossOriginWindow.focus === crossOriginWindow.focus // => false`

This patch implements [[CrossOriginPropertyDescriptorMap]], bringing consistent function identity
and aligning WebKit with the spec [1], Blink, and Gecko. For convenience, cache maps are added to
JSDOMGlobalObject (to accommodate RemoteDOMWindow) and cover both Window and Location objects.

As a cache map key, a pair of lexical global object and raw function pointer is used, which guarantees
correctness even if Window and Location would expose cross-origin property of the same name.

This patch removes 9 custom getters, adds runtime lookup for "showModalDialog" (which is rare),
and removes [ForwardDeclareInHeader] extended attribute as it's now unused and non-trivial to generate.

Also, fixes cross-realm `postMessage.length` to equal 1 as per WebIDL.

[1] https://html.spec.whatwg.org/multipage/browsers.html#crossorigingetownpropertyhelper-(-o,-p-)

Tests: imported/w3c/web-platform-tests/html/browsers/origin/cross-origin-objects/cross-origin-objects-function-caching.html
       imported/w3c/web-platform-tests/html/browsers/origin/cross-origin-objects/cross-origin-objects-function-length.html
       imported/w3c/web-platform-tests/html/browsers/origin/cross-origin-objects/cross-origin-objects-function-name.html

* bindings/js/JSDOMGlobalObject.cpp:
(WebCore::JSDOMGlobalObject::JSDOMGlobalObject):
(WebCore::JSDOMGlobalObject::createCrossOriginFunction):
(WebCore::JSDOMGlobalObject::createCrossOriginGetterSetter):
* bindings/js/JSDOMGlobalObject.h:
* bindings/js/JSDOMWindowCustom.cpp:
(WebCore::jsDOMWindowGetOwnPropertySlotRestrictedAccess):
(WebCore::JSDOMWindow::getOwnPropertySlot):
* bindings/js/JSLocationCustom.cpp:
(WebCore::getOwnPropertySlotCommon):
(WebCore::JSC_DEFINE_CUSTOM_GETTER): Deleted.
* bindings/scripts/CodeGeneratorJS.pm:
(GenerateHeader):
(GenerateImplementation):
* bindings/scripts/IDLAttributes.json:
* page/DOMWindow.idl:
* page/History.idl:
* page/Location.idl:
* page/RemoteDOMWindow.idl:

LayoutTests:

* http/tests/navigation/process-swap-window-open-expected.txt:
* http/tests/navigation/process-swap-window-open.html:

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (274527 => 274528)


--- trunk/LayoutTests/ChangeLog	2021-03-16 22:52:14 UTC (rev 274527)
+++ trunk/LayoutTests/ChangeLog	2021-03-16 23:00:57 UTC (rev 274528)
@@ -1,3 +1,13 @@
+2021-03-16  Alexey Shvayka  <shvaikal...@gmail.com>
+
+        Cache cross-origin methods / accessors of Window and Location per lexical global object
+        https://bugs.webkit.org/show_bug.cgi?id=222739
+
+        Reviewed by Darin Adler.
+
+        * http/tests/navigation/process-swap-window-open-expected.txt:
+        * http/tests/navigation/process-swap-window-open.html:
+
 2021-03-16  Julian Gonzalez  <julian_a_gonza...@apple.com>
 
         ASSERTION FAILED: m_state == State::Committed in WebKit::FrameLoadState::didFailLoad()

Modified: trunk/LayoutTests/http/tests/navigation/process-swap-window-open-expected.txt (274527 => 274528)


--- trunk/LayoutTests/http/tests/navigation/process-swap-window-open-expected.txt	2021-03-16 22:52:14 UTC (rev 274527)
+++ trunk/LayoutTests/http/tests/navigation/process-swap-window-open-expected.txt	2021-03-16 23:00:57 UTC (rev 274528)
@@ -28,6 +28,11 @@
 PASS w.focus is an instance of Function
 PASS w.blur is an instance of Function
 PASS w.postMessage is an instance of Function
+PASS w.close is w.close
+PASS w.focus is w.focus
+PASS w.blur is w.blur
+PASS w.postMessage is w.postMessage
+PASS w.postMessage.length is 1
 PASS w.postMessage('test', '*') did not throw exception.
 PASS w.focus() did not throw exception.
 PASS w.blur() did not throw exception.

Modified: trunk/LayoutTests/http/tests/navigation/process-swap-window-open.html (274527 => 274528)


--- trunk/LayoutTests/http/tests/navigation/process-swap-window-open.html	2021-03-16 22:52:14 UTC (rev 274527)
+++ trunk/LayoutTests/http/tests/navigation/process-swap-window-open.html	2021-03-16 23:00:57 UTC (rev 274528)
@@ -36,6 +36,11 @@
     shouldBeType("w.focus", "Function");
     shouldBeType("w.blur", "Function");
     shouldBeType("w.postMessage", "Function");
+    shouldBe("w.close", "w.close");
+    shouldBe("w.focus", "w.focus");
+    shouldBe("w.blur", "w.blur");
+    shouldBe("w.postMessage", "w.postMessage");
+    shouldBe("w.postMessage.length", "1");
     shouldNotThrow("w.postMessage('test', '*')");
     shouldNotThrow("w.focus()");
     shouldNotThrow("w.blur()");

Modified: trunk/LayoutTests/imported/w3c/ChangeLog (274527 => 274528)


--- trunk/LayoutTests/imported/w3c/ChangeLog	2021-03-16 22:52:14 UTC (rev 274527)
+++ trunk/LayoutTests/imported/w3c/ChangeLog	2021-03-16 23:00:57 UTC (rev 274528)
@@ -1,3 +1,18 @@
+2021-03-16  Alexey Shvayka  <shvaikal...@gmail.com>
+
+        Cache cross-origin methods / accessors of Window and Location per lexical global object
+        https://bugs.webkit.org/show_bug.cgi?id=222739
+
+        Reviewed by Darin Adler.
+
+        * web-platform-tests/html/browsers/origin/cross-origin-objects/cross-origin-objects-function-caching-expected.txt: Added.
+        * web-platform-tests/html/browsers/origin/cross-origin-objects/cross-origin-objects-function-caching.html: Added.
+        * web-platform-tests/html/browsers/origin/cross-origin-objects/cross-origin-objects-function-common.js: Added.
+        * web-platform-tests/html/browsers/origin/cross-origin-objects/cross-origin-objects-function-length-expected.txt: Added.
+        * web-platform-tests/html/browsers/origin/cross-origin-objects/cross-origin-objects-function-length.html: Added.
+        * web-platform-tests/html/browsers/origin/cross-origin-objects/cross-origin-objects-function-name-expected.txt: Added.
+        * web-platform-tests/html/browsers/origin/cross-origin-objects/cross-origin-objects-function-name.html: Added.
+
 2021-03-16  Ziran Sun  <z...@igalia.com>
 
         [css-grid] Replace the use of -1 with WTF::nullopt

Added: trunk/LayoutTests/imported/w3c/web-platform-tests/html/browsers/origin/cross-origin-objects/cross-origin-objects-function-caching-expected.txt (0 => 274528)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/html/browsers/origin/cross-origin-objects/cross-origin-objects-function-caching-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/html/browsers/origin/cross-origin-objects/cross-origin-objects-function-caching-expected.txt	2021-03-16 23:00:57 UTC (rev 274528)
@@ -0,0 +1,6 @@
+
+PASS Cross-origin Window methods are cached
+PASS Cross-origin Window accessors are cached
+PASS Cross-origin Location `replace` method is cached
+PASS Cross-origin Location `href` setter is cached
+

Added: trunk/LayoutTests/imported/w3c/web-platform-tests/html/browsers/origin/cross-origin-objects/cross-origin-objects-function-caching.html (0 => 274528)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/html/browsers/origin/cross-origin-objects/cross-origin-objects-function-caching.html	                        (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/html/browsers/origin/cross-origin-objects/cross-origin-objects-function-caching.html	2021-03-16 23:00:57 UTC (rev 274528)
@@ -0,0 +1,49 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Cross-origin methods and accessors are cached per Realm via[[CrossOriginPropertyDescriptorMap]]</title>
+<link rel="help" href=""
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+<div id=log></div>
+<script>
+"use strict";
+
+promise_test(async t => {
+    const w = await makeCrossOriginWindow(t);
+    for (const {key} of crossOriginWindowMethods) {
+        assert_equals(w[key], w[key], `w.${key} via [[Get]]`);
+        const desc1 = Object.getOwnPropertyDescriptor(w, key);
+        const desc2 = Object.getOwnPropertyDescriptor(w, key);
+        assert_equals(desc1.value, desc2.value, `w.${key} via [[GetOwnProperty]]`);
+    }
+}, "Cross-origin Window methods are cached");
+
+promise_test(async t => {
+    const w = await makeCrossOriginWindow(t);
+    for (const {key} of crossOriginWindowAccessors) {
+        const desc1 = Object.getOwnPropertyDescriptor(w, key);
+        const desc2 = Object.getOwnPropertyDescriptor(w, key);
+        assert_equals(desc1.get, desc2.get, `w.${key} getter`);
+        if (key === "location") {
+            assert_equals(desc1.set, desc2.set, `w.${key} setter`);
+        }
+    }
+}, "Cross-origin Window accessors are cached");
+
+promise_test(async t => {
+    const w = await makeCrossOriginWindow(t);
+    assert_equals(w.location.replace, w.location.replace, "via [[Get]]");
+    const desc1 = Object.getOwnPropertyDescriptor(w.location, "replace");
+    const desc2 = Object.getOwnPropertyDescriptor(w.location, "replace");
+    assert_equals(desc1.value, desc2.value, "via [[GetOwnProperty]]");
+}, "Cross-origin Location `replace` method is cached");
+
+promise_test(async t => {
+    const w = await makeCrossOriginWindow(t);
+    const desc1 = Object.getOwnPropertyDescriptor(w.location, "href");
+    const desc2 = Object.getOwnPropertyDescriptor(w.location, "href");
+    assert_equals(desc1.set, desc2.set);
+}, "Cross-origin Location `href` setter is cached");
+</script>

Added: trunk/LayoutTests/imported/w3c/web-platform-tests/html/browsers/origin/cross-origin-objects/cross-origin-objects-function-common.js (0 => 274528)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/html/browsers/origin/cross-origin-objects/cross-origin-objects-function-common.js	                        (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/html/browsers/origin/cross-origin-objects/cross-origin-objects-function-common.js	2021-03-16 23:00:57 UTC (rev 274528)
@@ -0,0 +1,34 @@
+"use strict";
+
+const crossOriginWindowMethods = [
+    {key: "close", length: 0},
+    {key: "focus", length: 0},
+    {key: "blur", length: 0},
+    {key: "postMessage", length: 1},
+];
+
+const crossOriginWindowAccessors = [
+    "window",
+    "self",
+    "location",
+    "closed",
+    "frames",
+    "length",
+    "top",
+    "opener",
+    "parent",
+].map(key => ({key}));
+
+const makeCrossOriginWindow = t => {
+    const iframe = document.createElement("iframe");
+    const path = location.pathname.slice(0, location.pathname.lastIndexOf("/")) + "/frame.html";
+    iframe.src = "" + path;
+
+    return new Promise((resolve, reject) => {
+        iframe._onload_ = () => { resolve(iframe.contentWindow); };
+        iframe._onerror_ = reject;
+
+        document.body.append(iframe);
+        t.add_cleanup(() => { iframe.remove(); });
+    });
+};

Added: trunk/LayoutTests/imported/w3c/web-platform-tests/html/browsers/origin/cross-origin-objects/cross-origin-objects-function-length-expected.txt (0 => 274528)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/html/browsers/origin/cross-origin-objects/cross-origin-objects-function-length-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/html/browsers/origin/cross-origin-objects/cross-origin-objects-function-length-expected.txt	2021-03-16 23:00:57 UTC (rev 274528)
@@ -0,0 +1,6 @@
+
+PASS Cross-origin Window methods have correct 'length'
+PASS Cross-origin Window accessors have correct 'length'
+PASS Cross-origin Location `replace` method has correct 'length'
+PASS Cross-origin Location `href` setter has correct 'length'
+

Added: trunk/LayoutTests/imported/w3c/web-platform-tests/html/browsers/origin/cross-origin-objects/cross-origin-objects-function-length.html (0 => 274528)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/html/browsers/origin/cross-origin-objects/cross-origin-objects-function-length.html	                        (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/html/browsers/origin/cross-origin-objects/cross-origin-objects-function-length.html	2021-03-16 23:00:57 UTC (rev 274528)
@@ -0,0 +1,45 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Cross-origin methods and accessors are created with correct 'length' property</title>
+<link rel="help" href=""
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+<div id=log></div>
+<script>
+"use strict";
+
+promise_test(async t => {
+    const w = await makeCrossOriginWindow(t);
+    for (const {key, length} of crossOriginWindowMethods) {
+        assert_equals(w[key].length, length, `w.${key} via [[Get]]`);
+        const desc = Object.getOwnPropertyDescriptor(w, key);
+        assert_equals(desc.value.length, length, `w.${key} via [[GetOwnProperty]]`);
+    }
+}, "Cross-origin Window methods have correct 'length'");
+
+promise_test(async t => {
+    const w = await makeCrossOriginWindow(t);
+    for (const {key} of crossOriginWindowAccessors) {
+        const desc = Object.getOwnPropertyDescriptor(w, key);
+        assert_equals(desc.get.length, 0, `w.${key}`);
+        if (key === "location") {
+            assert_equals(desc.set.length, 1, `w.${key}`);
+        }
+    }
+}, "Cross-origin Window accessors have correct 'length'");
+
+promise_test(async t => {
+    const w = await makeCrossOriginWindow(t);
+    assert_equals(w.location.replace.length, 1);
+    const desc = Object.getOwnPropertyDescriptor(w.location, "replace");
+    assert_equals(desc.value.length, 1);
+}, "Cross-origin Location `replace` method has correct 'length'");
+
+promise_test(async t => {
+    const w = await makeCrossOriginWindow(t);
+    const desc = Object.getOwnPropertyDescriptor(w.location, "href");
+    assert_equals(desc.set.length, 1);
+}, "Cross-origin Location `href` setter has correct 'length'");
+</script>

Added: trunk/LayoutTests/imported/w3c/web-platform-tests/html/browsers/origin/cross-origin-objects/cross-origin-objects-function-name-expected.txt (0 => 274528)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/html/browsers/origin/cross-origin-objects/cross-origin-objects-function-name-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/html/browsers/origin/cross-origin-objects/cross-origin-objects-function-name-expected.txt	2021-03-16 23:00:57 UTC (rev 274528)
@@ -0,0 +1,6 @@
+
+PASS Cross-origin Window methods have correct 'name'
+PASS Cross-origin Window accessors have correct 'name'
+PASS Cross-origin Location `replace` method has correct 'name'
+PASS Cross-origin Location `href` setter has correct 'name'
+

Added: trunk/LayoutTests/imported/w3c/web-platform-tests/html/browsers/origin/cross-origin-objects/cross-origin-objects-function-name.html (0 => 274528)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/html/browsers/origin/cross-origin-objects/cross-origin-objects-function-name.html	                        (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/html/browsers/origin/cross-origin-objects/cross-origin-objects-function-name.html	2021-03-16 23:00:57 UTC (rev 274528)
@@ -0,0 +1,45 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Cross-origin methods and accessors are created with correct 'name' property</title>
+<link rel="help" href=""
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+<div id=log></div>
+<script>
+"use strict";
+
+promise_test(async t => {
+    const w = await makeCrossOriginWindow(t);
+    for (const {key} of crossOriginWindowMethods) {
+        assert_equals(w[key].name, key, `w.${key} via [[Get]]`);
+        const desc = Object.getOwnPropertyDescriptor(w, key);
+        assert_equals(desc.value.name, key, `w.${key} via [[GetOwnProperty]]`);
+    }
+}, "Cross-origin Window methods have correct 'name'");
+
+promise_test(async t => {
+    const w = await makeCrossOriginWindow(t);
+    for (const {key} of crossOriginWindowAccessors) {
+        const desc = Object.getOwnPropertyDescriptor(w, key);
+        assert_equals(desc.get.name, `get ${key}`);
+        if (key === "location") {
+            assert_equals(desc.set.name, `set ${key}`);
+        }
+    }
+}, "Cross-origin Window accessors have correct 'name'");
+
+promise_test(async t => {
+    const w = await makeCrossOriginWindow(t);
+    assert_equals(w.location.replace.name, "replace");
+    const desc = Object.getOwnPropertyDescriptor(w.location, "replace");
+    assert_equals(desc.value.name, "replace");
+}, "Cross-origin Location `replace` method has correct 'name'");
+
+promise_test(async t => {
+    const w = await makeCrossOriginWindow(t);
+    const desc = Object.getOwnPropertyDescriptor(w.location, "href");
+    assert_equals(desc.set.name, "set href");
+}, "Cross-origin Location `href` setter has correct 'name'");
+</script>

Modified: trunk/Source/_javascript_Core/ChangeLog (274527 => 274528)


--- trunk/Source/_javascript_Core/ChangeLog	2021-03-16 22:52:14 UTC (rev 274527)
+++ trunk/Source/_javascript_Core/ChangeLog	2021-03-16 23:00:57 UTC (rev 274528)
@@ -1,3 +1,31 @@
+2021-03-16  Alexey Shvayka  <shvaikal...@gmail.com>
+
+        Cache cross-origin methods / accessors of Window and Location per lexical global object
+        https://bugs.webkit.org/show_bug.cgi?id=222739
+
+        Reviewed by Darin Adler.
+
+        1. Introduce WeakGCMap::ensureValue() to clean up JSObject::getOwnPropertyDescriptor() and
+           avoid double hashing. It decorates HashMap::ensure() to guarantee non-null return value.
+        2. Assert early that JSCustom{Getter,Setter}Function is created with non-null function pointer.
+        3. Rename getCustom{Getter,Setter}Function() to align with newly-added JSDOMGlobalObject methods.
+
+        * runtime/JSCustomGetterFunction.cpp:
+        (JSC::JSC_DEFINE_HOST_FUNCTION):
+        (JSC::JSCustomGetterFunction::create):
+        * runtime/JSCustomSetterFunction.cpp:
+        (JSC::JSC_DEFINE_HOST_FUNCTION):
+        (JSC::JSCustomSetterFunction::create):
+        * runtime/JSObject.cpp:
+        (JSC::createCustomGetterFunction):
+        (JSC::createCustomSetterFunction):
+        (JSC::JSObject::getOwnPropertyDescriptor):
+        (JSC::getCustomGetterFunction): Deleted.
+        (JSC::getCustomSetterFunction): Deleted.
+        * runtime/Lookup.h:
+        (JSC::nonCachingStaticFunctionGetterImpl): Deleted.
+        * runtime/WeakGCMap.h:
+
 2021-03-16  Mark Lam  <mark....@apple.com>
 
         Add a RootMarkReason printer and also add a few additional reasons.

Modified: trunk/Source/_javascript_Core/runtime/JSCustomGetterFunction.cpp (274527 => 274528)


--- trunk/Source/_javascript_Core/runtime/JSCustomGetterFunction.cpp	2021-03-16 22:52:14 UTC (rev 274527)
+++ trunk/Source/_javascript_Core/runtime/JSCustomGetterFunction.cpp	2021-03-16 23:00:57 UTC (rev 274528)
@@ -40,9 +40,7 @@
 
     JSCustomGetterFunction* customGetterFunction = jsCast<JSCustomGetterFunction*>(callFrame->jsCallee());
     JSValue thisValue = callFrame->thisValue();
-
     GetValueFunc getter = customGetterFunction->getter();
-    ASSERT(getter);
 
     if (auto domAttribute = customGetterFunction->domAttribute()) {
         if (!thisValue.inherits(vm, domAttribute->classInfo))
@@ -62,6 +60,7 @@
 
 JSCustomGetterFunction* JSCustomGetterFunction::create(VM& vm, JSGlobalObject* globalObject, const PropertyName& propertyName, GetValueFunc getter, Optional<DOMAttributeAnnotation> domAttribute)
 {
+    ASSERT(getter);
     NativeExecutable* executable = vm.getHostFunction(customGetterFunctionCall, callHostFunctionAsConstructor, String(propertyName.publicName()));
     Structure* structure = globalObject->customGetterFunctionStructure();
     JSCustomGetterFunction* function = new (NotNull, allocateCell<JSCustomGetterFunction>(vm.heap)) JSCustomGetterFunction(vm, executable, globalObject, structure, propertyName, getter, domAttribute);

Modified: trunk/Source/_javascript_Core/runtime/JSCustomSetterFunction.cpp (274527 => 274528)


--- trunk/Source/_javascript_Core/runtime/JSCustomSetterFunction.cpp	2021-03-16 22:52:14 UTC (rev 274527)
+++ trunk/Source/_javascript_Core/runtime/JSCustomSetterFunction.cpp	2021-03-16 23:00:57 UTC (rev 274528)
@@ -36,7 +36,6 @@
 JSC_DEFINE_HOST_FUNCTION(customSetterFunctionCall, (JSGlobalObject* globalObject, CallFrame* callFrame))
 {
     PutValueFunc setter = jsCast<JSCustomSetterFunction*>(callFrame->jsCallee())->setter();
-    ASSERT(setter);
     setter(globalObject, JSValue::encode(callFrame->thisValue()), JSValue::encode(callFrame->argument(0)));
     return JSValue::encode(jsUndefined());
 }
@@ -49,6 +48,7 @@
 
 JSCustomSetterFunction* JSCustomSetterFunction::create(VM& vm, JSGlobalObject* globalObject, const PropertyName& propertyName, PutValueFunc setter)
 {
+    ASSERT(setter);
     NativeExecutable* executable = vm.getHostFunction(customSetterFunctionCall, callHostFunctionAsConstructor, String(propertyName.publicName()));
     Structure* structure = globalObject->customSetterFunctionStructure();
     JSCustomSetterFunction* function = new (NotNull, allocateCell<JSCustomSetterFunction>(vm.heap)) JSCustomSetterFunction(vm, executable, globalObject, structure, setter);

Modified: trunk/Source/_javascript_Core/runtime/JSObject.cpp (274527 => 274528)


--- trunk/Source/_javascript_Core/runtime/JSObject.cpp	2021-03-16 22:52:14 UTC (rev 274527)
+++ trunk/Source/_javascript_Core/runtime/JSObject.cpp	2021-03-16 23:00:57 UTC (rev 274528)
@@ -3521,24 +3521,18 @@
     return Butterfly::createOrGrowPropertyStorage(butterfly(), vm, this, structure(vm), oldSize, newSize);
 }
 
-static JSCustomGetterFunction* getCustomGetterFunction(JSGlobalObject* globalObject, PropertyName propertyName, GetValueFunc getValueFunc, Optional<DOMAttributeAnnotation> domAttribute)
+static JSCustomGetterFunction* createCustomGetterFunction(JSGlobalObject* globalObject, PropertyName propertyName, GetValueFunc getValueFunc, Optional<DOMAttributeAnnotation> domAttribute)
 {
-    JSCustomGetterFunction* customGetterFunction = globalObject->customGetterFunctionMap().get(getValueFunc);
-    if (!customGetterFunction) {
-        customGetterFunction = JSCustomGetterFunction::create(globalObject->vm(), globalObject, propertyName, getValueFunc, domAttribute);
-        globalObject->customGetterFunctionMap().set(getValueFunc, customGetterFunction);
-    }
-    return customGetterFunction;
+    return globalObject->customGetterFunctionMap().ensureValue(getValueFunc, [&] {
+        return JSCustomGetterFunction::create(globalObject->vm(), globalObject, propertyName, getValueFunc, domAttribute);
+    });
 }
 
-static JSCustomSetterFunction* getCustomSetterFunction(JSGlobalObject* globalObject, PropertyName propertyName, PutValueFunc putValueFunc)
+static JSCustomSetterFunction* createCustomSetterFunction(JSGlobalObject* globalObject, PropertyName propertyName, PutValueFunc putValueFunc)
 {
-    JSCustomSetterFunction* customSetterFunction = globalObject->customSetterFunctionMap().get(putValueFunc);
-    if (!customSetterFunction) {
-        customSetterFunction = JSCustomSetterFunction::create(globalObject->vm(), globalObject, propertyName, putValueFunc);
-        globalObject->customSetterFunctionMap().set(putValueFunc, customSetterFunction);
-    }
-    return customSetterFunction;
+    return globalObject->customSetterFunctionMap().ensureValue(putValueFunc, [&] {
+        return JSCustomSetterFunction::create(globalObject->vm(), globalObject, propertyName, putValueFunc);
+    });
 }
 
 bool JSObject::getOwnPropertyDescriptor(JSGlobalObject* globalObject, PropertyName propertyName, PropertyDescriptor& descriptor)
@@ -3559,9 +3553,9 @@
         descriptor.setAccessorDescriptor((slot.attributes() | PropertyAttribute::Accessor) & ~PropertyAttribute::CustomAccessor);
         JSGlobalObject* slotBaseGlobalObject = slot.slotBase()->globalObject(vm);
         if (slot.customGetter())
-            descriptor.setGetter(getCustomGetterFunction(slotBaseGlobalObject, propertyName, slot.customGetter(), slot.domAttribute()));
+            descriptor.setGetter(createCustomGetterFunction(slotBaseGlobalObject, propertyName, slot.customGetter(), slot.domAttribute()));
         if (slot.customSetter())
-            descriptor.setSetter(getCustomSetterFunction(slotBaseGlobalObject, propertyName, slot.customSetter()));
+            descriptor.setSetter(createCustomSetterFunction(slotBaseGlobalObject, propertyName, slot.customSetter()));
     } else {
         JSValue value = slot.getValue(globalObject, propertyName);
         RETURN_IF_EXCEPTION(scope, false);

Modified: trunk/Source/_javascript_Core/runtime/Lookup.h (274527 => 274528)


--- trunk/Source/_javascript_Core/runtime/Lookup.h	2021-03-16 22:52:14 UTC (rev 274527)
+++ trunk/Source/_javascript_Core/runtime/Lookup.h	2021-03-16 23:00:57 UTC (rev 274528)
@@ -414,9 +414,4 @@
     }
 }
 
-template<RawNativeFunction nativeFunction, int length> EncodedJSValue nonCachingStaticFunctionGetterImpl(JSGlobalObject* globalObject, PropertyName propertyName)
-{
-    return JSValue::encode(JSFunction::create(globalObject->vm(), globalObject, length, propertyName.publicName(), nativeFunction));
-}
-
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/runtime/WeakGCMap.h (274527 => 274528)


--- trunk/Source/_javascript_Core/runtime/WeakGCMap.h	2021-03-16 22:52:14 UTC (rev 274527)
+++ trunk/Source/_javascript_Core/runtime/WeakGCMap.h	2021-03-16 23:00:57 UTC (rev 274528)
@@ -64,6 +64,18 @@
         return m_map.set(key, WTFMove(value));
     }
 
+    template<typename Functor>
+    ValueArg* ensureValue(const KeyType& key, Functor&& functor)
+    {
+        AddResult result = m_map.ensure(key, std::forward<Functor>(functor));
+        ValueArg* value = result.iterator->value.get();
+        if (!result.isNewEntry && !value) {
+            value = functor();
+            result.iterator->value = WTFMove(value);
+        }
+        return value;
+    }
+
     bool remove(const KeyType& key)
     {
         return m_map.remove(key);

Modified: trunk/Source/WebCore/ChangeLog (274527 => 274528)


--- trunk/Source/WebCore/ChangeLog	2021-03-16 22:52:14 UTC (rev 274527)
+++ trunk/Source/WebCore/ChangeLog	2021-03-16 23:00:57 UTC (rev 274528)
@@ -1,3 +1,55 @@
+2021-03-16  Alexey Shvayka  <shvaikal...@gmail.com>
+
+        Cache cross-origin methods / accessors of Window and Location per lexical global object
+        https://bugs.webkit.org/show_bug.cgi?id=222739
+
+        Reviewed by Darin Adler.
+
+        For cross-origin methods / accessors, Window and Location objects return different JSFunction
+        instances on every [[Get]]. The intent was to ensure isolation by supplying different Realms with
+        different function objects. However, within the same callee Realm, this makes subsequent lookups
+        of a cross-origin method / accessor fail reference equality test, which is rather confusing:
+
+            `crossOriginWindow.focus === crossOriginWindow.focus // => false`
+
+        This patch implements [[CrossOriginPropertyDescriptorMap]], bringing consistent function identity
+        and aligning WebKit with the spec [1], Blink, and Gecko. For convenience, cache maps are added to
+        JSDOMGlobalObject (to accommodate RemoteDOMWindow) and cover both Window and Location objects.
+
+        As a cache map key, a pair of lexical global object and raw function pointer is used, which guarantees
+        correctness even if Window and Location would expose cross-origin property of the same name.
+
+        This patch removes 9 custom getters, adds runtime lookup for "showModalDialog" (which is rare),
+        and removes [ForwardDeclareInHeader] extended attribute as it's now unused and non-trivial to generate.
+
+        Also, fixes cross-realm `postMessage.length` to equal 1 as per WebIDL.
+
+        [1] https://html.spec.whatwg.org/multipage/browsers.html#crossorigingetownpropertyhelper-(-o,-p-)
+
+        Tests: imported/w3c/web-platform-tests/html/browsers/origin/cross-origin-objects/cross-origin-objects-function-caching.html
+               imported/w3c/web-platform-tests/html/browsers/origin/cross-origin-objects/cross-origin-objects-function-length.html
+               imported/w3c/web-platform-tests/html/browsers/origin/cross-origin-objects/cross-origin-objects-function-name.html
+
+        * bindings/js/JSDOMGlobalObject.cpp:
+        (WebCore::JSDOMGlobalObject::JSDOMGlobalObject):
+        (WebCore::JSDOMGlobalObject::createCrossOriginFunction):
+        (WebCore::JSDOMGlobalObject::createCrossOriginGetterSetter):
+        * bindings/js/JSDOMGlobalObject.h:
+        * bindings/js/JSDOMWindowCustom.cpp:
+        (WebCore::jsDOMWindowGetOwnPropertySlotRestrictedAccess):
+        (WebCore::JSDOMWindow::getOwnPropertySlot):
+        * bindings/js/JSLocationCustom.cpp:
+        (WebCore::getOwnPropertySlotCommon):
+        (WebCore::JSC_DEFINE_CUSTOM_GETTER): Deleted.
+        * bindings/scripts/CodeGeneratorJS.pm:
+        (GenerateHeader):
+        (GenerateImplementation):
+        * bindings/scripts/IDLAttributes.json:
+        * page/DOMWindow.idl:
+        * page/History.idl:
+        * page/Location.idl:
+        * page/RemoteDOMWindow.idl:
+
 2021-03-16  Chris Dumez  <cdu...@apple.com>
 
         Avoid heap allocation under AudioDestinationCocoa::render()

Modified: trunk/Source/WebCore/bindings/js/JSDOMGlobalObject.cpp (274527 => 274528)


--- trunk/Source/WebCore/bindings/js/JSDOMGlobalObject.cpp	2021-03-16 22:52:14 UTC (rev 274527)
+++ trunk/Source/WebCore/bindings/js/JSDOMGlobalObject.cpp	2021-03-16 23:00:57 UTC (rev 274528)
@@ -54,9 +54,13 @@
 #include "WorkletGlobalScope.h"
 #include <_javascript_Core/BuiltinNames.h>
 #include <_javascript_Core/CodeBlock.h>
+#include <_javascript_Core/GetterSetter.h>
+#include <_javascript_Core/JSCustomGetterFunction.h>
+#include <_javascript_Core/JSCustomSetterFunction.h>
 #include <_javascript_Core/JSInternalPromise.h>
 #include <_javascript_Core/StructureInlines.h>
 #include <_javascript_Core/WasmStreamingCompiler.h>
+#include <_javascript_Core/WeakGCMapInlines.h>
 
 namespace WebCore {
 using namespace JSC;
@@ -75,6 +79,8 @@
     , m_world(WTFMove(world))
     , m_worldIsNormal(m_world->isNormal())
     , m_builtinInternalFunctions(vm)
+    , m_crossOriginFunctionMap(vm)
+    , m_crossOriginGetterSetterMap(vm)
 {
 }
 
@@ -298,6 +304,26 @@
         guarded->clear();
 }
 
+JSFunction* JSDOMGlobalObject::createCrossOriginFunction(JSGlobalObject* lexicalGlobalObject, PropertyName propertyName, NativeFunction nativeFunction, unsigned length)
+{
+    CrossOriginMapKey key = std::make_pair(lexicalGlobalObject, nativeFunction.rawPointer());
+    return m_crossOriginFunctionMap.ensureValue(key, [&] {
+        return JSFunction::create(lexicalGlobalObject->vm(), lexicalGlobalObject, length, propertyName.publicName(), nativeFunction);
+    });
+}
+
+GetterSetter* JSDOMGlobalObject::createCrossOriginGetterSetter(JSGlobalObject* lexicalGlobalObject, PropertyName propertyName, GetValueFunc getter, PutValueFunc setter)
+{
+    ASSERT(getter || setter);
+    CrossOriginMapKey key = std::make_pair(lexicalGlobalObject, getter ? reinterpret_cast<void*>(getter) : reinterpret_cast<void*>(setter));
+    return m_crossOriginGetterSetterMap.ensureValue(key, [&] {
+        auto& vm = lexicalGlobalObject->vm();
+        return GetterSetter::create(vm, lexicalGlobalObject,
+            getter ? JSCustomGetterFunction::create(vm, lexicalGlobalObject, propertyName, getter) : nullptr,
+            setter ? JSCustomSetterFunction::create(vm, lexicalGlobalObject, propertyName, setter) : nullptr);
+    });
+}
+
 #if ENABLE(WEBASSEMBLY)
 // https://webassembly.github.io/spec/web-api/index.html#compile-a-potential-webassembly-response
 static JSC::JSPromise* handleResponseOnStreamingAction(JSC::JSGlobalObject* globalObject, JSC::JSValue source, JSC::Wasm::CompilerMode compilerMode, JSC::JSObject* importObject)

Modified: trunk/Source/WebCore/bindings/js/JSDOMGlobalObject.h (274527 => 274528)


--- trunk/Source/WebCore/bindings/js/JSDOMGlobalObject.h	2021-03-16 22:52:14 UTC (rev 274527)
+++ trunk/Source/WebCore/bindings/js/JSDOMGlobalObject.h	2021-03-16 23:00:57 UTC (rev 274528)
@@ -31,6 +31,7 @@
 #include <_javascript_Core/JSGlobalObject.h>
 #include <_javascript_Core/JSObjectInlines.h>
 #include <_javascript_Core/LockDuringMarking.h>
+#include <_javascript_Core/WeakGCMap.h>
 
 namespace WebCore {
 
@@ -83,6 +84,9 @@
 
     JSC::JSProxy& proxy() const { ASSERT(m_proxy); return *m_proxy.get(); }
 
+    JSC::JSFunction* createCrossOriginFunction(JSC::JSGlobalObject*, JSC::PropertyName, JSC::NativeFunction, unsigned length);
+    JSC::GetterSetter* createCrossOriginGetterSetter(JSC::JSGlobalObject*, JSC::PropertyName, JSC::GetValueFunc, JSC::PutValueFunc);
+
 public:
     ~JSDOMGlobalObject();
 
@@ -124,7 +128,11 @@
     void addBuiltinGlobals(JSC::VM&);
     friend void JSBuiltinInternalFunctions::initialize(JSDOMGlobalObject&);
 
+    using CrossOriginMapKey = std::pair<JSC::JSGlobalObject*, void*>;
+
     JSBuiltinInternalFunctions m_builtinInternalFunctions;
+    JSC::WeakGCMap<CrossOriginMapKey, JSC::JSFunction> m_crossOriginFunctionMap;
+    JSC::WeakGCMap<CrossOriginMapKey, JSC::GetterSetter> m_crossOriginGetterSetterMap;
 };
 
 template<class ConstructorClass>

Modified: trunk/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp (274527 => 274528)


--- trunk/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp	2021-03-16 22:52:14 UTC (rev 274527)
+++ trunk/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp	2021-03-16 23:00:57 UTC (rev 274528)
@@ -48,12 +48,9 @@
 #include "Settings.h"
 #include "WebCoreJSClientData.h"
 #include <_javascript_Core/BuiltinNames.h>
-#include <_javascript_Core/GetterSetter.h>
 #include <_javascript_Core/HeapAnalyzer.h>
 #include <_javascript_Core/InternalFunction.h>
 #include <_javascript_Core/JSCInlines.h>
-#include <_javascript_Core/JSCustomGetterFunction.h>
-#include <_javascript_Core/JSCustomSetterFunction.h>
 #include <_javascript_Core/JSFunction.h>
 #include <_javascript_Core/JSMicrotask.h>
 #include <_javascript_Core/Lookup.h>
@@ -67,58 +64,10 @@
 using namespace JSC;
 
 static JSC_DECLARE_HOST_FUNCTION(jsDOMWindowInstanceFunction_openDatabase);
-static JSC_DECLARE_CUSTOM_GETTER(jsRemoteDOMWindowInstanceFunction_blurNonCaching);
-static JSC_DECLARE_CUSTOM_GETTER(jsDOMWindowInstanceFunction_blurNonCaching);
-static JSC_DECLARE_CUSTOM_GETTER(jsRemoteDOMWindowInstanceFunction_closeNonCaching);
-static JSC_DECLARE_CUSTOM_GETTER(jsDOMWindowInstanceFunction_closeNonCaching);
-static JSC_DECLARE_CUSTOM_GETTER(jsRemoteDOMWindowInstanceFunction_focusNonCaching);
-static JSC_DECLARE_CUSTOM_GETTER(jsDOMWindowInstanceFunction_focusNonCaching);
-static JSC_DECLARE_CUSTOM_GETTER(jsRemoteDOMWindowInstanceFunction_postMessageNonCaching);
-static JSC_DECLARE_CUSTOM_GETTER(jsDOMWindowInstanceFunction_postMessageNonCaching);
 #if ENABLE(USER_MESSAGE_HANDLERS)
 static JSC_DECLARE_CUSTOM_GETTER(jsDOMWindow_webkit);
 #endif
 
-JSC_DEFINE_CUSTOM_GETTER(jsRemoteDOMWindowInstanceFunction_blurNonCaching, (JSGlobalObject* globalObject, EncodedJSValue, PropertyName propertyName))
-{
-    return nonCachingStaticFunctionGetterImpl<jsRemoteDOMWindowInstanceFunction_blur, 0>(globalObject, propertyName);
-}
-
-JSC_DEFINE_CUSTOM_GETTER(jsDOMWindowInstanceFunction_blurNonCaching, (JSGlobalObject* globalObject, EncodedJSValue, PropertyName propertyName))
-{
-    return nonCachingStaticFunctionGetterImpl<jsDOMWindowInstanceFunction_blur, 0>(globalObject, propertyName);
-}
-
-JSC_DEFINE_CUSTOM_GETTER(jsRemoteDOMWindowInstanceFunction_closeNonCaching, (JSGlobalObject* globalObject, EncodedJSValue, PropertyName propertyName))
-{
-    return nonCachingStaticFunctionGetterImpl<jsRemoteDOMWindowInstanceFunction_close, 0>(globalObject, propertyName);
-}
-
-JSC_DEFINE_CUSTOM_GETTER(jsDOMWindowInstanceFunction_closeNonCaching, (JSGlobalObject* globalObject, EncodedJSValue, PropertyName propertyName))
-{
-    return nonCachingStaticFunctionGetterImpl<jsDOMWindowInstanceFunction_close, 0>(globalObject, propertyName);
-}
-
-JSC_DEFINE_CUSTOM_GETTER(jsRemoteDOMWindowInstanceFunction_focusNonCaching, (JSGlobalObject* globalObject, EncodedJSValue, PropertyName propertyName))
-{
-    return nonCachingStaticFunctionGetterImpl<jsRemoteDOMWindowInstanceFunction_focus, 0>(globalObject, propertyName);
-}
-
-JSC_DEFINE_CUSTOM_GETTER(jsDOMWindowInstanceFunction_focusNonCaching, (JSGlobalObject* globalObject, EncodedJSValue, PropertyName propertyName))
-{
-    return nonCachingStaticFunctionGetterImpl<jsDOMWindowInstanceFunction_focus, 0>(globalObject, propertyName);
-}
-
-JSC_DEFINE_CUSTOM_GETTER(jsRemoteDOMWindowInstanceFunction_postMessageNonCaching, (JSGlobalObject* globalObject, EncodedJSValue, PropertyName propertyName))
-{
-    return nonCachingStaticFunctionGetterImpl<jsRemoteDOMWindowInstanceFunction_postMessage, 0>(globalObject, propertyName);
-}
-
-JSC_DEFINE_CUSTOM_GETTER(jsDOMWindowInstanceFunction_postMessageNonCaching, (JSGlobalObject* globalObject, EncodedJSValue, PropertyName propertyName))
-{
-    return nonCachingStaticFunctionGetterImpl<jsDOMWindowInstanceFunction_postMessage, 2>(globalObject, propertyName);
-}
-
 template<typename Visitor>
 void JSDOMWindow::visitAdditionalChildren(Visitor& visitor)
 {
@@ -157,45 +106,34 @@
     // https://html.spec.whatwg.org/#crossorigingetownpropertyhelper-(-o,-p-)
 
     // These are the functions we allow access to cross-origin (DoNotCheckSecurity in IDL).
-    // Always provide the original function, on a fresh uncached function object.
-    if (propertyName == builtinNames.blurPublicName()) {
-        slot.setCustom(thisObject, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum), windowType == DOMWindowType::Remote ? jsRemoteDOMWindowInstanceFunction_blurNonCaching : jsDOMWindowInstanceFunction_blurNonCaching);
+    auto* classInfo = windowType == DOMWindowType::Remote ? JSRemoteDOMWindow::info() : JSDOMWindow::info();
+    if (propertyName == builtinNames.closePublicName()
+        || propertyName == builtinNames.focusPublicName()
+        || propertyName == builtinNames.blurPublicName()
+        || propertyName == builtinNames.postMessagePublicName()) {
+        auto* entry = classInfo->staticPropHashTable->entry(propertyName);
+        auto* jsFunction = thisObject->createCrossOriginFunction(&lexicalGlobalObject, propertyName, entry->function(), entry->functionLength());
+        slot.setValue(thisObject, PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum, jsFunction);
         return true;
     }
-    if (propertyName == builtinNames.closePublicName()) {
-        slot.setCustom(thisObject, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum), windowType == DOMWindowType::Remote ? jsRemoteDOMWindowInstanceFunction_closeNonCaching : jsDOMWindowInstanceFunction_closeNonCaching);
-        return true;
-    }
-    if (propertyName == builtinNames.focusPublicName()) {
-        slot.setCustom(thisObject, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum), windowType == DOMWindowType::Remote ? jsRemoteDOMWindowInstanceFunction_focusNonCaching : jsDOMWindowInstanceFunction_focusNonCaching);
-        return true;
-    }
-    if (propertyName == builtinNames.postMessagePublicName()) {
-        slot.setCustom(thisObject, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum), windowType == DOMWindowType::Remote ? jsRemoteDOMWindowInstanceFunction_postMessageNonCaching : jsDOMWindowInstanceFunction_postMessageNonCaching);
-        return true;
-    }
 
     // When accessing cross-origin known Window properties, we always use the original property getter,
     // even if the property was removed / redefined. As of early 2016, this matches Firefox and Chrome's
     // behavior.
-    auto* classInfo = windowType == DOMWindowType::Remote ? JSRemoteDOMWindow::info() : JSDOMWindow::info();
-    if (auto* entry = classInfo->staticPropHashTable->entry(propertyName)) {
-        // Only allow access to these specific properties.
-        if (propertyName == builtinNames.locationPublicName()
-            || propertyName == builtinNames.closedPublicName()
-            || propertyName == vm.propertyNames->length
-            || propertyName == builtinNames.selfPublicName()
-            || propertyName == builtinNames.windowPublicName()
-            || propertyName == builtinNames.framesPublicName()
-            || propertyName == builtinNames.openerPublicName()
-            || propertyName == builtinNames.parentPublicName()
-            || propertyName == builtinNames.topPublicName()) {
-            auto* getter = JSCustomGetterFunction::create(vm, &lexicalGlobalObject, propertyName, entry->propertyGetter());
-            auto* setter = propertyName == builtinNames.locationPublicName() ? JSCustomSetterFunction::create(vm, &lexicalGlobalObject, propertyName, entry->propertyPutter()) : nullptr;
-            auto* getterSetter = GetterSetter::create(vm, &lexicalGlobalObject, getter, setter);
-            slot.setGetterSlot(thisObject, PropertyAttribute::Accessor | PropertyAttribute::DontEnum, getterSetter);
-            return true;
-        }
+    if (propertyName == builtinNames.windowPublicName()
+        || propertyName == builtinNames.selfPublicName()
+        || propertyName == builtinNames.locationPublicName()
+        || propertyName == builtinNames.closedPublicName()
+        || propertyName == builtinNames.framesPublicName()
+        || propertyName == vm.propertyNames->length
+        || propertyName == builtinNames.topPublicName()
+        || propertyName == builtinNames.openerPublicName()
+        || propertyName == builtinNames.parentPublicName()) {
+        auto* entry = classInfo->staticPropHashTable->entry(propertyName);
+        auto* setter = propertyName == builtinNames.locationPublicName() ? entry->propertyPutter() : nullptr;
+        auto* getterSetter = thisObject->createCrossOriginGetterSetter(&lexicalGlobalObject, propertyName, entry->propertyGetter(), setter);
+        slot.setGetterSlot(thisObject, PropertyAttribute::Accessor | PropertyAttribute::DontEnum, getterSetter);
+        return true;
     }
 
     // Check for child frames by name before built-in properties to match Mozilla. This does
@@ -265,7 +203,7 @@
         // Detect when we're getting the property 'showModalDialog', this is disabled, and has its original value.
         bool isShowModalDialogAndShouldHide = propertyName == static_cast<JSVMClientData*>(lexicalGlobalObject->vm().clientData)->builtinNames().showModalDialogPublicName()
             && (!frame || !DOMWindow::canShowModalDialog(*frame))
-            && slot.isValue() && isHostFunction(slot.getValue(lexicalGlobalObject, propertyName), jsDOMWindowInstanceFunction_showModalDialog);
+            && slot.isValue() && isHostFunction(slot.getValue(lexicalGlobalObject, propertyName), s_info.staticPropHashTable->entry(propertyName)->function());
         // Unless we're in the showModalDialog special case, we're done.
         if (!isShowModalDialogAndShouldHide)
             return true;

Modified: trunk/Source/WebCore/bindings/js/JSLocationCustom.cpp (274527 => 274528)


--- trunk/Source/WebCore/bindings/js/JSLocationCustom.cpp	2021-03-16 22:52:14 UTC (rev 274527)
+++ trunk/Source/WebCore/bindings/js/JSLocationCustom.cpp	2021-03-16 23:00:57 UTC (rev 274528)
@@ -29,8 +29,6 @@
 #include "JSDOMWindowCustom.h"
 #include "RuntimeApplicationChecks.h"
 #include "WebCoreJSClientData.h"
-#include <_javascript_Core/GetterSetter.h>
-#include <_javascript_Core/JSCustomSetterFunction.h>
 #include <_javascript_Core/JSFunction.h>
 #include <_javascript_Core/Lookup.h>
 
@@ -37,13 +35,6 @@
 namespace WebCore {
 using namespace JSC;
 
-static JSC_DECLARE_CUSTOM_GETTER(jsLocationInstanceFunction_replaceNonCaching);
-
-JSC_DEFINE_CUSTOM_GETTER(jsLocationInstanceFunction_replaceNonCaching, (JSGlobalObject* globalObject, EncodedJSValue, PropertyName propertyName))
-{
-    return nonCachingStaticFunctionGetterImpl<jsLocationInstanceFunction_replace, 1>(globalObject, propertyName);
-}
-
 static bool getOwnPropertySlotCommon(JSLocation& thisObject, JSGlobalObject& lexicalGlobalObject, PropertyName propertyName, PropertySlot& slot)
 {
     VM& vm = lexicalGlobalObject.vm();
@@ -64,7 +55,9 @@
 
     // We only allow access to Location.replace() cross origin.
     if (propertyName == vm.propertyNames->replace) {
-        slot.setCustom(&thisObject, static_cast<unsigned>(PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum), jsLocationInstanceFunction_replaceNonCaching);
+        auto* entry = JSLocation::info()->staticPropHashTable->entry(propertyName);
+        auto* jsFunction = thisObject.globalObject()->createCrossOriginFunction(&lexicalGlobalObject, propertyName, entry->function(), entry->functionLength());
+        slot.setValue(&thisObject, PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum, jsFunction);
         return true;
     }
 
@@ -72,8 +65,7 @@
     // a descriptor that has a setter but no getter.
     if (slot.internalMethodType() == PropertySlot::InternalMethodType::GetOwnProperty && propertyName == static_cast<JSVMClientData*>(vm.clientData)->builtinNames().hrefPublicName()) {
         auto* entry = JSLocation::info()->staticPropHashTable->entry(propertyName);
-        auto* setter = JSCustomSetterFunction::create(vm, &lexicalGlobalObject, propertyName, entry->propertyPutter());
-        auto* getterSetter = GetterSetter::create(vm, &lexicalGlobalObject, nullptr, setter);
+        auto* getterSetter = thisObject.globalObject()->createCrossOriginGetterSetter(&lexicalGlobalObject, propertyName, nullptr, entry->propertyPutter());
         slot.setGetterSlot(&thisObject, PropertyAttribute::Accessor | PropertyAttribute::DontEnum, getterSetter);
         return true;
     }

Modified: trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm (274527 => 274528)


--- trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm	2021-03-16 22:52:14 UTC (rev 274527)
+++ trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm	2021-03-16 23:00:57 UTC (rev 274528)
@@ -3066,9 +3066,6 @@
     my $numCustomOperations = 0;
     my $numCustomAttributes = 0;
 
-    my $hasForwardDeclaringOperations = 0;
-    my $hasForwardDeclaringAttributes = 0;
-
     my $hasDOMJITAttributes = 0;
 
     # Attribute and function enums
@@ -3084,8 +3081,6 @@
                 push(@headerContent, "#endif\n") if $conditionalString;
             }
             $hasDOMJITAttributes = 1 if $attribute->extendedAttributes->{DOMJIT};
-
-            $hasForwardDeclaringAttributes = 1 if $attribute->extendedAttributes->{ForwardDeclareInHeader};
         }
     }
 
@@ -3144,7 +3139,6 @@
 
     foreach my $operation (@{$interface->operations}) {
         $numCustomOperations++ if HasCustomMethod($operation);
-        $hasForwardDeclaringOperations = 1 if $operation->extendedAttributes->{ForwardDeclareInHeader};
     }
 
     if ($numCustomOperations > 0) {
@@ -3270,52 +3264,6 @@
 
     GeneratePrototypeDeclaration(\@headerContent, $className, $interface) if HeaderNeedsPrototypeDeclaration($interface);
 
-    if ($hasForwardDeclaringOperations) {
-        my $inAppleCopyright = 0;
-        push(@headerContent,"// Functions\n\n");
-        foreach my $operation (@{$interface->operations}) {
-            next if $operation->{overloadIndex} && $operation->{overloadIndex} > 1;
-            next unless $operation->extendedAttributes->{ForwardDeclareInHeader};
-
-            if ($operation->extendedAttributes->{AppleCopyright}) {
-                if (!$inAppleCopyright) {
-                    push(@headerContent, $beginAppleCopyrightForHeaderFiles);
-                    $inAppleCopyright = 1;
-                }
-            } elsif ($inAppleCopyright) {
-                push(@headerContent, $endAppleCopyright);
-                $inAppleCopyright = 0;
-            }
-
-            my $conditionalAttribute = GetConditionalForOperationConsideringOverloads($operation);
-            my $conditionalString = $conditionalAttribute ? $codeGenerator->GenerateConditionalStringFromAttributeValue($conditionalAttribute) : undef;
-            push(@headerContent, "#if ${conditionalString}\n") if $conditionalString;
-            my $functionName = GetFunctionName($interface, $className, $operation);
-            push(@headerContent, "JSC_DECLARE_HOST_FUNCTION(${functionName});\n");
-            push(@headerContent, "#endif\n") if $conditionalString;
-        }
-
-        push(@headerContent, $endAppleCopyright) if $inAppleCopyright;
-        push(@headerContent,"\n");
-    }
-
-    if ($hasForwardDeclaringAttributes) {
-        push(@headerContent,"// Attributes\n\n");
-        foreach my $attribute (@{$interface->attributes}) {
-            next unless $attribute->extendedAttributes->{ForwardDeclareInHeader};
-
-            my $conditionalString = $codeGenerator->GenerateConditionalString($attribute);
-            push(@headerContent, "#if ${conditionalString}\n") if $conditionalString;
-            my $getter = GetAttributeGetterName($interface, $className, $attribute);
-            push(@headerContent, "JSC_DECLARE_CUSTOM_GETTER(${getter});\n");
-            if (!IsReadonly($attribute)) {
-                my $setter = GetAttributeSetterName($interface, $className, $attribute);
-                push(@headerContent, "JSC_DECLARE_CUSTOM_SETTER(${setter});\n");
-            }
-            push(@headerContent, "#endif\n") if $conditionalString;
-        }
-    }
-
     # CheckJSCast Snippet function.
     if ($interface->extendedAttributes->{DOMJIT}) {
         $headerIncludes{"<_javascript_Core/Snippet.h>"} = 1;
@@ -4307,7 +4255,6 @@
         push(@implContent,"// Functions\n\n");
         foreach my $operation (@{$interface->operations}) {
             next if $operation->{overloadIndex} && $operation->{overloadIndex} > 1;
-            next if $operation->extendedAttributes->{ForwardDeclareInHeader};
             next if IsJSBuiltin($interface, $operation);
             next if $operation->name eq "[Symbol.Iterator]";
 
@@ -4353,7 +4300,6 @@
         }
 
         foreach my $attribute (@{$interface->attributes}) {
-            next if $attribute->extendedAttributes->{ForwardDeclareInHeader};
             next if IsJSBuiltin($interface, $attribute);
 
             my $conditionalString = $codeGenerator->GenerateConditionalString($attribute);

Modified: trunk/Source/WebCore/bindings/scripts/IDLAttributes.json (274527 => 274528)


--- trunk/Source/WebCore/bindings/scripts/IDLAttributes.json	2021-03-16 22:52:14 UTC (rev 274527)
+++ trunk/Source/WebCore/bindings/scripts/IDLAttributes.json	2021-03-16 23:00:57 UTC (rev 274528)
@@ -223,9 +223,6 @@
                 "url": "https://heycam.github.io/webidl/#Exposed"
             }
         },
-        "ForwardDeclareInHeader": {
-            "contextsAllowed": ["attribute", "operation"]
-        },
         "GenerateIsReachable": {
             "contextsAllowed": ["interface"],
             "values": ["", "Impl", "ImplWebGLRenderingContext", "ImplCanvasBase", "ImplDocument", "ImplElementRoot", "ImplOwnerNodeRoot", "ImplScriptExecutionContext", "ReachableFromDOMWindow", "ReachableFromNavigator"]

Modified: trunk/Source/WebCore/page/DOMWindow.idl (274527 => 274528)


--- trunk/Source/WebCore/page/DOMWindow.idl	2021-03-16 22:52:14 UTC (rev 274527)
+++ trunk/Source/WebCore/page/DOMWindow.idl	2021-03-16 23:00:57 UTC (rev 274528)
@@ -62,11 +62,11 @@
     [Replaceable] readonly attribute BarProp statusbar;
     [Replaceable] readonly attribute BarProp toolbar;
     attribute DOMString status;
-    [DoNotCheckSecurity, CallWith=IncumbentDocument, ForwardDeclareInHeader] undefined close();
-    [DoNotCheckSecurity, ForwardDeclareInHeader] readonly attribute boolean closed;
+    [DoNotCheckSecurity, CallWith=IncumbentDocument] undefined close();
+    [DoNotCheckSecurity] readonly attribute boolean closed;
     undefined stop();
-    [DoNotCheckSecurity, CallWith=IncumbentWindow, ForwardDeclareInHeader] undefined focus();
-    [DoNotCheckSecurity, ForwardDeclareInHeader] undefined blur();
+    [DoNotCheckSecurity, CallWith=IncumbentWindow] undefined focus();
+    [DoNotCheckSecurity] undefined blur();
 
     // other browsing contexts
     [Replaceable, DoNotCheckSecurityOnGetter, CustomGetter] readonly attribute WindowProxy frames;
@@ -91,8 +91,8 @@
     DOMString? prompt(optional DOMString message = "", optional DOMString defaultValue = "");
     undefined print();
 
-    [CallWith=GlobalObject&IncumbentWindow, DoNotCheckSecurity, ForwardDeclareInHeader, MayThrowException] undefined postMessage(any message, USVString targetOrigin, optional sequence<object> transfer = []);
-    [CallWith=GlobalObject&IncumbentWindow, DoNotCheckSecurity, ForwardDeclareInHeader, MayThrowException] undefined postMessage(any message, optional WindowPostMessageOptions options);
+    [CallWith=GlobalObject&IncumbentWindow, DoNotCheckSecurity, MayThrowException] undefined postMessage(any message, USVString targetOrigin, optional sequence<object> transfer = []);
+    [CallWith=GlobalObject&IncumbentWindow, DoNotCheckSecurity, MayThrowException] undefined postMessage(any message, optional WindowPostMessageOptions options);
 
 
     // Obsolete: Still part of the HTML specification (https://html.spec.whatwg.org/#Window-partial).
@@ -119,7 +119,7 @@
     [NotEnumerable, Conditional=IOS_GESTURE_EVENTS] attribute EventHandler ongesturestart;
 
     // Non-standard: This has been dropped from the HTML specification and by other browsers.
-    [Custom, ForwardDeclareInHeader] any showModalDialog(DOMString url, optional any dialogArgs, optional DOMString featureArgs);
+    [Custom] any showModalDialog(DOMString url, optional any dialogArgs, optional DOMString featureArgs);
 
     // Non-standard: should probably deprecate this (https://bugs.webkit.org/show_bug.cgi?id=79653).
     // Blink already deprecated it (https://bugs.chromium.org/p/chromium/issues/detail?id=437569).

Modified: trunk/Source/WebCore/page/History.idl (274527 => 274528)


--- trunk/Source/WebCore/page/History.idl	2021-03-16 22:52:14 UTC (rev 274527)
+++ trunk/Source/WebCore/page/History.idl	2021-03-16 23:00:57 UTC (rev 274528)
@@ -33,9 +33,9 @@
     attribute ScrollRestoration scrollRestoration;
     [Custom] readonly attribute any state;
 
-    [CallWith=Document, ForwardDeclareInHeader] undefined back();
-    [CallWith=Document, ForwardDeclareInHeader] undefined forward();
-    [CallWith=Document, ForwardDeclareInHeader] undefined go(optional long delta = 0);
+    [CallWith=Document] undefined back();
+    [CallWith=Document] undefined forward();
+    [CallWith=Document] undefined go(optional long delta = 0);
 
     // FIXME: title should not be nullable as per the HTML specification.
     [MayThrowException] undefined pushState(SerializedScriptValue data, DOMString? title, optional USVString? url = ""

Modified: trunk/Source/WebCore/page/Location.idl (274527 => 274528)


--- trunk/Source/WebCore/page/Location.idl	2021-03-16 22:52:14 UTC (rev 274527)
+++ trunk/Source/WebCore/page/Location.idl	2021-03-16 23:00:57 UTC (rev 274528)
@@ -45,9 +45,9 @@
 ] interface Location {
     [SetterCallWith=ActiveWindow&FirstWindow, DoNotCheckSecurityOnSetter] stringifier attribute USVString href;
 
-    [CallWith=ActiveWindow&FirstWindow, MayThrowException, ForwardDeclareInHeader] undefined assign(USVString url);
-    [DoNotCheckSecurity, CallWith=ActiveWindow&FirstWindow, MayThrowException, ForwardDeclareInHeader] undefined replace(USVString url);
-    [CallWith=ActiveWindow, ForwardDeclareInHeader] undefined reload();
+    [CallWith=ActiveWindow&FirstWindow, MayThrowException] undefined assign(USVString url);
+    [DoNotCheckSecurity, CallWith=ActiveWindow&FirstWindow, MayThrowException] undefined replace(USVString url);
+    [CallWith=ActiveWindow] undefined reload();
 
     // URI decomposition attributes
     [SetterCallWith=ActiveWindow&FirstWindow] attribute USVString protocol;

Modified: trunk/Source/WebCore/page/RemoteDOMWindow.idl (274527 => 274528)


--- trunk/Source/WebCore/page/RemoteDOMWindow.idl	2021-03-16 22:52:14 UTC (rev 274527)
+++ trunk/Source/WebCore/page/RemoteDOMWindow.idl	2021-03-16 23:00:57 UTC (rev 274528)
@@ -46,14 +46,14 @@
     [LegacyUnforgeable, ImplementedAs=self] readonly attribute WindowProxy window;
     [Replaceable] readonly attribute WindowProxy self;
     [PutForwards=href, LegacyUnforgeable] readonly attribute Location? location; // FIXME: Should not be nullable.
-    [CallWith=IncumbentDocument, ForwardDeclareInHeader] undefined close();
-    [ForwardDeclareInHeader] readonly attribute boolean closed;
-    [CallWith=IncumbentWindow, ForwardDeclareInHeader] undefined focus();
-    [ForwardDeclareInHeader] undefined blur();
+    [CallWith=IncumbentDocument] undefined close();
+    readonly attribute boolean closed;
+    [CallWith=IncumbentWindow] undefined focus();
+    undefined blur();
     [Replaceable, ImplementedAs=self] readonly attribute WindowProxy frames;
     [Replaceable] readonly attribute unsigned long length;
     [LegacyUnforgeable] readonly attribute WindowProxy? top;
     readonly attribute WindowProxy? opener;
     [Replaceable] readonly attribute WindowProxy? parent;
-    [CallWith=GlobalObject&IncumbentWindow, ForwardDeclareInHeader] undefined postMessage(any message, USVString targetOrigin, optional sequence<object> transfer = []);
+    [CallWith=GlobalObject&IncumbentWindow] undefined postMessage(any message, USVString targetOrigin, optional sequence<object> transfer = []);
 };
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to