<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[196583] trunk/Source/WebCore</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/196583">196583</a></dd>
<dt>Author</dt> <dd>barraclough@apple.com</dd>
<dt>Date</dt> <dd>2016-02-15 11:56:18 -0800 (Mon, 15 Feb 2016)</dd>
</dl>
<h3>Log Message</h3>
<pre>Organize, deduplicate & comment JSDOMWindowCustom getOwnPropertySlot
https://bugs.webkit.org/show_bug.cgi?id=154224
Reviewed by Chris Dumez.
* bindings/js/JSDOMWindowCustom.cpp:
(WebCore::jsDOMWindowGetOwnPropertySlotRestrictedAccess):
(WebCore::jsDOMWindowGetOwnPropertySlotNamedItemGetter):
(WebCore::JSDOMWindow::getOwnPropertySlot):
(WebCore::JSDOMWindow::getOwnPropertySlotByIndex):
- organized property access sequence into a more logical order, removed
duplicated code & added comments.
(WebCore::namedItemGetter): Deleted.
- there was no need for a custom callback here; merged functionality into
jsDOMWindowGetOwnPropertySlotNamedItemGetter.
(WebCore::jsDOMWindowGetOwnPropertySlotCrossOrigin): Deleted.
- renamed to jsDOMWindowGetOwnPropertySlotRestrictedAccess
(this now also handles frameless access).</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSDOMWindowCustomcpp">trunk/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (196582 => 196583)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-02-15 18:54:30 UTC (rev 196582)
+++ trunk/Source/WebCore/ChangeLog        2016-02-15 19:56:18 UTC (rev 196583)
</span><span class="lines">@@ -1,3 +1,24 @@
</span><ins>+2016-02-14 Gavin Barraclough <barraclough@apple.com>
+
+ Organize, deduplicate & comment JSDOMWindowCustom getOwnPropertySlot
+ https://bugs.webkit.org/show_bug.cgi?id=154224
+
+ Reviewed by Chris Dumez.
+
+ * bindings/js/JSDOMWindowCustom.cpp:
+ (WebCore::jsDOMWindowGetOwnPropertySlotRestrictedAccess):
+ (WebCore::jsDOMWindowGetOwnPropertySlotNamedItemGetter):
+ (WebCore::JSDOMWindow::getOwnPropertySlot):
+ (WebCore::JSDOMWindow::getOwnPropertySlotByIndex):
+ - organized property access sequence into a more logical order, removed
+ duplicated code & added comments.
+ (WebCore::namedItemGetter): Deleted.
+ - there was no need for a custom callback here; merged functionality into
+ jsDOMWindowGetOwnPropertySlotNamedItemGetter.
+ (WebCore::jsDOMWindowGetOwnPropertySlotCrossOrigin): Deleted.
+ - renamed to jsDOMWindowGetOwnPropertySlotRestrictedAccess
+ (this now also handles frameless access).
+
</ins><span class="cx"> 2016-02-15 Daniel Bates <dabates@apple.com>
</span><span class="cx">
</span><span class="cx"> CSP: 'sandbox' should be ignored in report-only mode
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSDOMWindowCustomcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp (196582 => 196583)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp        2016-02-15 18:54:30 UTC (rev 196582)
+++ trunk/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp        2016-02-15 19:56:18 UTC (rev 196583)
</span><span class="lines">@@ -66,27 +66,6 @@
</span><span class="cx"> visitor.addOpaqueRoot(frame);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-static EncodedJSValue namedItemGetter(ExecState* exec, EncodedJSValue thisValue, PropertyName propertyName)
-{
- JSDOMWindowBase* thisObj = jsCast<JSDOMWindow*>(JSValue::decode(thisValue));
- Document* document = thisObj->wrapped().frame()->document();
-
- ASSERT(BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObj->wrapped()));
- ASSERT(is<HTMLDocument>(document));
-
- AtomicStringImpl* atomicPropertyName = propertyName.publicName();
- if (!atomicPropertyName || !downcast<HTMLDocument>(*document).hasWindowNamedItem(*atomicPropertyName))
- return JSValue::encode(jsUndefined());
-
- if (UNLIKELY(downcast<HTMLDocument>(*document).windowNamedItemContainsMultipleElements(*atomicPropertyName))) {
- Ref<HTMLCollection> collection = document->windowNamedItems(atomicPropertyName);
- ASSERT(collection->length() > 1);
- return JSValue::encode(toJS(exec, thisObj->globalObject(), WTF::getPtr(collection)));
- }
-
- return JSValue::encode(toJS(exec, thisObj->globalObject(), downcast<HTMLDocument>(*document).windowNamedItem(*atomicPropertyName)));
-}
-
</del><span class="cx"> #if ENABLE(USER_MESSAGE_HANDLERS)
</span><span class="cx"> static EncodedJSValue jsDOMWindowWebKit(ExecState* exec, EncodedJSValue thisValue, PropertyName)
</span><span class="cx"> {
</span><span class="lines">@@ -112,8 +91,34 @@
</span><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="cx">
</span><del>-static bool jsDOMWindowGetOwnPropertySlotCrossOrigin(JSDOMWindow* thisObject, ExecState* exec, PropertyName propertyName, PropertySlot& slot, String& errorMessage)
</del><ins>+static bool jsDOMWindowGetOwnPropertySlotRestrictedAccess(JSDOMWindow* thisObject, Frame* frame, ExecState* exec, PropertyName propertyName, PropertySlot& slot, String& errorMessage)
</ins><span class="cx"> {
</span><ins>+ // Allow access to toString() cross-domain, but always Object.prototype.toString.
+ if (propertyName == exec->propertyNames().toString) {
+ slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, nonCachingStaticFunctionGetter<objectProtoFuncToString, 0>);
+ return true;
+ }
+
+ // We don't want any properties other than "close" and "closed" on a frameless window
+ // (i.e. one whose page got closed, or whose iframe got removed).
+ // FIXME: This handling for frameless windows duplicates similar behaviour for cross-origin
+ // access below; we should try to find a way to merge the two.
+ if (!frame) {
+ if (propertyName == exec->propertyNames().closed) {
+ slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, jsDOMWindowClosed);
+ return true;
+ }
+ if (propertyName == exec->propertyNames().close) {
+ slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionClose, 0>);
+ return true;
+ }
+
+ // FIXME: We should have a message here that explains why the property access/function call was
+ // not allowed.
+ slot.setUndefined();
+ return true;
+ }
+
</ins><span class="cx"> // These are the functions we allow access to cross-origin (DoNotCheckSecurity in IDL).
</span><span class="cx"> // Always provide the original function, on a fresh uncached function object.
</span><span class="cx"> if (propertyName == exec->propertyNames().blur) {
</span><span class="lines">@@ -133,12 +138,6 @@
</span><span class="cx"> return true;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- // Allow access to toString() cross-domain, but always Object.prototype.toString.
- if (propertyName == exec->propertyNames().toString) {
- slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, nonCachingStaticFunctionGetter<objectProtoFuncToString, 0>);
- return true;
- }
-
</del><span class="cx"> // When accessing cross-origin known Window properties, we always use the original property getter,
</span><span class="cx"> // even if the property was removed / redefined. As of early 2016, this matches Firefox and Chrome's
</span><span class="cx"> // behavior.
</span><span class="lines">@@ -177,129 +176,130 @@
</span><span class="cx"> return true;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-#if ENABLE(USER_MESSAGE_HANDLERS)
- if (propertyName == exec->propertyNames().webkit && thisObject->wrapped().shouldHaveWebKitNamespaceForWorld(thisObject->world())) {
- slot.setCacheableCustom(thisObject, ReadOnly | DontDelete | DontEnum, jsDOMWindowWebKit);
- return true;
- }
-#endif
-
- // After this point it is no longer valid to cache any results because of
- // the impure nature of the property accesses which follow. We can move this
- // statement further down when we add ways to mitigate these impurities with,
- // for example, watchpoints.
- slot.disableCaching();
-
- // Check for child frames by name before built-in properties to
- // match Mozilla. This does not match IE, but some sites end up
- // naming frames things that conflict with window properties that
- // are in Moz but not IE. Since we have some of these, we have to do
- // it the Moz way.
- if (auto* scopedChild = thisObject->wrapped().frame()->tree().scopedChild(propertyNameToAtomicString(propertyName))) {
</del><ins>+ // Check for child frames by name before built-in properties to match Mozilla. This does
+ // not match IE, but some sites end up naming frames things that conflict with window
+ // properties that are in Moz but not IE. Since we have some of these, we have to do it
+ // the Moz way.
+ if (auto* scopedChild = frame->tree().scopedChild(propertyNameToAtomicString(propertyName))) {
</ins><span class="cx"> slot.setValue(thisObject, ReadOnly | DontDelete | DontEnum, toJS(exec, scopedChild->document()->domWindow()));
</span><span class="cx"> return true;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- // allow window[1] or parent[1] etc. (#56983)
- Optional<uint32_t> index = parseIndex(propertyName);
- if (index && index.value() < thisObject->wrapped().frame()->tree().scopedChildCount()) {
- slot.setValue(thisObject, ReadOnly | DontDelete | DontEnum,
- toJS(exec, thisObject->wrapped().frame()->tree().scopedChild(index.value())->document()->domWindow()));
- return true;
- }
-
</del><span class="cx"> thisObject->printErrorMessage(errorMessage);
</span><span class="cx"> slot.setUndefined();
</span><span class="cx"> return true;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-bool JSDOMWindow::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
</del><ins>+static bool jsDOMWindowGetOwnPropertySlotNamedItemGetter(JSDOMWindow* thisObject, Frame& frame, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
</ins><span class="cx"> {
</span><del>- JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(object);
- // When accessing a Window cross-domain, functions are always the native built-in ones, and they
- // are not affected by properties changed on the Window or anything in its prototype chain.
- // This is consistent with the behavior of Firefox.
</del><ins>+ // FIXME: If the property is present on the prototype we should 'return false;', not
+ // return the property. This is supposed to be an 'own' access.
+ JSValue proto = thisObject->prototype();
+ if (proto.isObject() && asObject(proto)->getPropertySlot(exec, propertyName, slot))
+ return true;
</ins><span class="cx">
</span><del>- // We don't want any properties other than "close" and "closed" on a frameless window (i.e. one whose page got closed,
- // or whose iframe got removed).
- // FIXME: This doesn't fully match Firefox, which allows at least toString in addition to those.
- if (!thisObject->wrapped().frame()) {
- // The following code is safe for cross-domain and same domain use.
- // It ignores any custom properties that might be set on the DOMWindow (including a custom prototype).
- if (propertyName == exec->propertyNames().closed) {
- slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, jsDOMWindowClosed);
</del><ins>+ // Check for child frames by name before built-in properties to match Mozilla. This does
+ // not match IE, but some sites end up naming frames things that conflict with window
+ // properties that are in Moz but not IE. Since we have some of these, we have to do it
+ // the Moz way.
+ if (auto* scopedChild = frame.tree().scopedChild(propertyNameToAtomicString(propertyName))) {
+ slot.setValue(thisObject, ReadOnly | DontDelete | DontEnum, toJS(exec, scopedChild->document()->domWindow()));
+ return true;
+ }
+
+ // FIXME: Search the whole frame hierarchy somewhere around here.
+ // We need to test the correct priority order.
+
+ // Allow shortcuts like 'Image1' instead of document.images.Image1
+ Document* document = frame.document();
+ if (is<HTMLDocument>(*document)) {
+ auto& htmlDocument = downcast<HTMLDocument>(*document);
+ auto* atomicPropertyName = propertyName.publicName();
+ if (atomicPropertyName && htmlDocument.hasWindowNamedItem(*atomicPropertyName)) {
+ JSValue namedItem;
+ if (UNLIKELY(htmlDocument.windowNamedItemContainsMultipleElements(*atomicPropertyName))) {
+ Ref<HTMLCollection> collection = document->windowNamedItems(atomicPropertyName);
+ ASSERT(collection->length() > 1);
+ namedItem = toJS(exec, thisObject->globalObject(), collection.ptr());
+ } else
+ namedItem = toJS(exec, thisObject->globalObject(), htmlDocument.windowNamedItem(*atomicPropertyName));
+ slot.setValue(thisObject, ReadOnly | DontDelete | DontEnum, namedItem);
</ins><span class="cx"> return true;
</span><span class="cx"> }
</span><del>- if (propertyName == exec->propertyNames().close) {
- slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionClose, 0>);
- return true;
- }
-
- // FIXME: We should have a message here that explains why the property access/function call was
- // not allowed.
- slot.setUndefined();
- return true;
</del><span class="cx"> }
</span><span class="cx">
</span><del>- slot.setWatchpointSet(thisObject->m_windowCloseWatchpoints);
</del><ins>+ return false;
+}
</ins><span class="cx">
</span><del>- // We need to check for cross-domain access here without printing the generic warning message
- // because we always allow access to some function, just different ones depending whether access
- // is allowed.
</del><ins>+// Property access sequence is:
+// (1) indexed properties,
+// (2) regular own properties,
+// (3) named properties (in fact, these shouldn't be on the window, should be on the NPO).
+bool JSDOMWindow::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
+{
+ // (1) First, indexed properties.
+ // Hand off all indexed access to getOwnPropertySlotByIndex, which supports the indexed getter.
+ if (Optional<unsigned> index = parseIndex(propertyName))
+ return getOwnPropertySlotByIndex(object, exec, index.value(), slot);
+
+ auto* thisObject = jsCast<JSDOMWindow*>(object);
+ auto* frame = thisObject->wrapped().frame();
+
+ // Hand off all cross-domain/frameless access to jsDOMWindowGetOwnPropertySlotRestrictedAccess.
</ins><span class="cx"> String errorMessage;
</span><del>- if (!shouldAllowAccessToDOMWindow(exec, thisObject->wrapped(), errorMessage))
- return jsDOMWindowGetOwnPropertySlotCrossOrigin(thisObject, exec, propertyName, slot, errorMessage);
</del><ins>+ if (!frame || !shouldAllowAccessToDOMWindow(exec, thisObject->wrapped(), errorMessage))
+ return jsDOMWindowGetOwnPropertySlotRestrictedAccess(thisObject, frame, exec, propertyName, slot, errorMessage);
</ins><span class="cx">
</span><del>- // Look for overrides before looking at any of our own properties, but ignore overrides completely
- // if this is cross-domain access.
- if (JSGlobalObject::getOwnPropertySlot(thisObject, exec, propertyName, slot))
</del><ins>+ // FIXME: this need more explanation.
+ // (Particularly, is it correct that this exists here but not in getOwnPropertySlotByIndex?)
+ slot.setWatchpointSet(thisObject->m_windowCloseWatchpoints);
+
+ // (2) Regular own properties.
+ // FIXME: we should probably be able to use getStaticPropertySlot here.
+ if (Base::getOwnPropertySlot(thisObject, exec, propertyName, slot))
</ins><span class="cx"> return true;
</span><del>-
- // We need this code here because otherwise JSDOMWindowBase will stop the search before we even get to the
- // prototype due to the blanket same origin (shouldAllowAccessToDOMWindow) check at the end of getOwnPropertySlot.
- // Also, it's important to get the implementation straight out of the DOMWindow prototype regardless of
- // what prototype is actually set on this object.
</del><ins>+ if (!thisObject->staticFunctionsReified()) {
+ if (auto* entry = JSDOMWindow::info()->staticPropHashTable->entry(propertyName)) {
+ slot.setCacheableCustom(thisObject, entry->attributes(), entry->propertyGetter());
+ return true;
+ }
+ }
+ // FIXME: These are all bogus. Keeping these here make some tests pass that check these properties
+ // are own properties of the window, but introduces other problems instead (e.g. if you overwrite
+ // & delete then the original value is restored!) Should be removed.
</ins><span class="cx"> if (propertyName == exec->propertyNames().blur) {
</span><span class="cx"> slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionBlur, 0>);
</span><span class="cx"> return true;
</span><del>- } else if (propertyName == exec->propertyNames().close) {
</del><ins>+ }
+ if (propertyName == exec->propertyNames().close) {
</ins><span class="cx"> slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionClose, 0>);
</span><span class="cx"> return true;
</span><del>- } else if (propertyName == exec->propertyNames().focus) {
</del><ins>+ }
+ if (propertyName == exec->propertyNames().focus) {
</ins><span class="cx"> slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionFocus, 0>);
</span><span class="cx"> return true;
</span><del>- } else if (propertyName == exec->propertyNames().postMessage) {
</del><ins>+ }
+ if (propertyName == exec->propertyNames().postMessage) {
</ins><span class="cx"> slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionPostMessage, 2>);
</span><span class="cx"> return true;
</span><del>- } else if (propertyName == exec->propertyNames().showModalDialog) {
- if (!DOMWindow::canShowModalDialog(thisObject->wrapped().frame())) {
- slot.setUndefined();
- return true;
- }
</del><span class="cx"> }
</span><del>-
</del><ins>+ // FIXME: this looks pretty bogus. It seems highly likely that if !canShowModalDialog the
+ // funtion should still be present, or should be omitted entirely - present but reads as
+ // undefined with unspecified attributes is likely wrong.
+ if (propertyName == exec->propertyNames().showModalDialog && !DOMWindow::canShowModalDialog(frame)) {
+ slot.setUndefined();
+ return true;
+ }
</ins><span class="cx"> #if ENABLE(INDEXED_DATABASE)
</span><span class="cx"> // FIXME: With generated JS bindings built on static property tables there is no way to
</span><del>- // completely remove a generated property at runtime.
- // So to completely disable IndexedDB at runtime we have to not generate these accessors
- // and have to handle them specially here.
</del><ins>+ // completely remove a generated property at runtime. So to completely disable IndexedDB
+ // at runtime we have to not generate these accessors and have to handle them specially here.
</ins><span class="cx"> // Once https://webkit.org/b/145669 is resolved, they can once again be auto generated.
</span><span class="cx"> if (RuntimeEnabledFeatures::sharedFeatures().indexedDBEnabled() && (propertyName == exec->propertyNames().indexedDB || propertyName == exec->propertyNames().webkitIndexedDB)) {
</span><span class="cx"> slot.setCustom(thisObject, DontDelete | ReadOnly | CustomAccessor, jsDOMWindowIndexedDB);
</span><span class="cx"> return true;
</span><span class="cx"> }
</span><span class="cx"> #endif
</span><del>-
- // 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.
- if (!thisObject->staticFunctionsReified()) {
- if (auto* entry = JSDOMWindow::info()->staticPropHashTable->entry(propertyName)) {
- slot.setCacheableCustom(thisObject, entry->attributes(), entry->propertyGetter());
- return true;
- }
- }
-
</del><span class="cx"> #if ENABLE(USER_MESSAGE_HANDLERS)
</span><span class="cx"> if (propertyName == exec->propertyNames().webkit && thisObject->wrapped().shouldHaveWebKitNamespaceForWorld(thisObject->world())) {
</span><span class="cx"> slot.setCacheableCustom(thisObject, DontDelete | ReadOnly, jsDOMWindowWebKit);
</span><span class="lines">@@ -307,119 +307,42 @@
</span><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="cx">
</span><del>- // Do prototype lookup early so that functions and attributes in the prototype can have
- // precedence over the index and name getters.
- JSValue proto = thisObject->prototype();
- if (proto.isObject() && asObject(proto)->getPropertySlot(exec, propertyName, slot))
- return true;
-
- // After this point it is no longer valid to cache any results because of
- // the impure nature of the property accesses which follow. We can move this
- // statement further down when we add ways to mitigate these impurities with,
- // for example, watchpoints.
- slot.disableCaching();
-
- // Check for child frames by name before built-in properties to
- // match Mozilla. This does not match IE, but some sites end up
- // naming frames things that conflict with window properties that
- // are in Moz but not IE. Since we have some of these, we have to do
- // it the Moz way.
- if (auto* scopedChild = thisObject->wrapped().frame()->tree().scopedChild(propertyNameToAtomicString(propertyName))) {
- slot.setValue(thisObject, ReadOnly | DontDelete | DontEnum, toJS(exec, scopedChild->document()->domWindow()));
- return true;
- }
-
- // FIXME: Search the whole frame hierarchy somewhere around here.
- // We need to test the correct priority order.
-
- // allow window[1] or parent[1] etc. (#56983)
- Optional<uint32_t> index = parseIndex(propertyName);
- if (index && index.value() < thisObject->wrapped().frame()->tree().scopedChildCount()) {
- slot.setValue(thisObject, ReadOnly | DontDelete | DontEnum,
- toJS(exec, thisObject->wrapped().frame()->tree().scopedChild(index.value())->document()->domWindow()));
- return true;
- }
-
- // Allow shortcuts like 'Image1' instead of document.images.Image1
- Document* document = thisObject->wrapped().frame()->document();
- if (is<HTMLDocument>(*document)) {
- AtomicStringImpl* atomicPropertyName = propertyName.publicName();
- if (atomicPropertyName && downcast<HTMLDocument>(*document).hasWindowNamedItem(*atomicPropertyName)) {
- slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, namedItemGetter);
- return true;
- }
- }
-
- return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
</del><ins>+ // (3) Finally, named properties.
+ // Really, this should just be 'return false;' - these should all be on the NPO.
+ return jsDOMWindowGetOwnPropertySlotNamedItemGetter(thisObject, *frame, exec, propertyName, slot);
</ins><span class="cx"> }
</span><span class="cx">
</span><ins>+// Property access sequence is:
+// (1) indexed properties,
+// (2) regular own properties,
+// (3) named properties (in fact, these shouldn't be on the window, should be on the NPO).
</ins><span class="cx"> bool JSDOMWindow::getOwnPropertySlotByIndex(JSObject* object, ExecState* exec, unsigned index, PropertySlot& slot)
</span><span class="cx"> {
</span><del>- JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(object);
-
- if (!thisObject->wrapped().frame()) {
- // FIXME: We should have a message here that explains why the property access/function call was
- // not allowed.
- slot.setUndefined();
- return true;
- }
</del><ins>+ auto* thisObject = jsCast<JSDOMWindow*>(object);
+ auto* frame = thisObject->wrapped().frame();
</ins><span class="cx">
</span><del>- Identifier propertyName = Identifier::from(exec, index);
-
- // We need to check for cross-domain access here without printing the generic warning message
- // because we always allow access to some function, just different ones depending whether access
- // is allowed.
- String errorMessage;
- if (!shouldAllowAccessToDOMWindow(exec, thisObject->wrapped(), errorMessage))
- return jsDOMWindowGetOwnPropertySlotCrossOrigin(thisObject, exec, propertyName, slot, errorMessage);
</del><ins>+ // Indexed getters take precendence over regular properties, so caching would be invalid.
+ slot.disableCaching();
</ins><span class="cx">
</span><del>- // Look for overrides before looking at any of our own properties, but ignore overrides completely
- // if this is cross-domain access.
- if (JSGlobalObject::getOwnPropertySlotByIndex(thisObject, exec, index, slot))
</del><ins>+ // (1) First, indexed properties.
+ // These are also allowed cross-orgin, so come before the access check.
+ if (frame && index < frame->tree().scopedChildCount()) {
+ slot.setValue(thisObject, ReadOnly | DontDelete | DontEnum, toJS(exec, frame->tree().scopedChild(index)->document()->domWindow()));
</ins><span class="cx"> return true;
</span><del>-
- // Check for child frames by name before built-in properties to
- // match Mozilla. This does not match IE, but some sites end up
- // naming frames things that conflict with window properties that
- // are in Moz but not IE. Since we have some of these, we have to do
- // it the Moz way.
- if (auto* scopedChild = thisObject->wrapped().frame()->tree().scopedChild(propertyNameToAtomicString(propertyName))) {
- slot.setValue(thisObject, ReadOnly | DontDelete | DontEnum, toJS(exec, scopedChild->document()->domWindow()));
- return true;
</del><span class="cx"> }
</span><del>-
- // Do prototype lookup early so that functions and attributes in the prototype can have
- // precedence over the index and name getters.
- JSValue proto = thisObject->prototype();
- if (proto.isObject()) {
- if (asObject(proto)->getPropertySlot(exec, index, slot))
- return true;
- }
</del><span class="cx">
</span><del>- // FIXME: Search the whole frame hierarchy somewhere around here.
- // We need to test the correct priority order.
</del><ins>+ // Hand off all cross-domain/frameless access to jsDOMWindowGetOwnPropertySlotRestrictedAccess.
+ String errorMessage;
+ if (!frame || !shouldAllowAccessToDOMWindow(exec, thisObject->wrapped(), errorMessage))
+ return jsDOMWindowGetOwnPropertySlotRestrictedAccess(thisObject, frame, exec, Identifier::from(exec, index), slot, errorMessage);
</ins><span class="cx">
</span><del>- // allow window[1] or parent[1] etc. (#56983)
- if (index < thisObject->wrapped().frame()->tree().scopedChildCount()) {
- slot.setValue(thisObject, ReadOnly | DontDelete | DontEnum,
- toJS(exec, thisObject->wrapped().frame()->tree().scopedChild(index)->document()->domWindow()));
</del><ins>+ // (2) Regular own properties.
+ if (Base::getOwnPropertySlotByIndex(thisObject, exec, index, slot))
</ins><span class="cx"> return true;
</span><del>- }
</del><span class="cx">
</span><del>- // Allow shortcuts like 'Image1' instead of document.images.Image1
- Document* document = thisObject->wrapped().frame()->document();
- if (is<HTMLDocument>(*document)) {
- // This propertyName is generated by Identifier::from.
- // This function generates Identifier from String and always returns the non-symbol Identifier.
- ASSERT(!propertyName.isSymbol());
- auto atomicPropertyName = static_cast<AtomicStringImpl*>(propertyName.impl());
- if (atomicPropertyName && downcast<HTMLDocument>(*document).hasWindowNamedItem(*atomicPropertyName)) {
- slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, namedItemGetter);
- return true;
- }
- }
-
- return Base::getOwnPropertySlotByIndex(thisObject, exec, index, slot);
</del><ins>+ // (3) Finally, named properties.
+ // Really, this should just be 'return false;' - these should all be on the NPO.
+ return jsDOMWindowGetOwnPropertySlotNamedItemGetter(thisObject, *frame, exec, Identifier::from(exec, index), slot);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> void JSDOMWindow::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
</span></span></pre>
</div>
</div>
</body>
</html>