<!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>[186955] trunk</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/186955">186955</a></dd>
<dt>Author</dt> <dd>mark.lam@apple.com</dd>
<dt>Date</dt> <dd>2015-07-17 11:11:40 -0700 (Fri, 17 Jul 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Remove leak of objects between isolated worlds on custom events, message events, and pop state events.
https://bugs.webkit.org/show_bug.cgi?id=118884

Reviewed by Filip Pizlo and Mark Lam.
Patch by Keith Miller  &lt;keith_miller@apple.com&gt;.

Source/WebCore:

Tests: fast/events/event-leak-objects.html
       fast/events/event-properties-gc.html

Fixes an issue where objects passed as certain properties of events could cross isolated worlds. This
was fixed by checking that any object passed by an event must be serializable or originate from the same
isolated world as the one it is currently being accessed in. In the case of MessageEvents and PopStateEvents we
cache the values of the data and state properties, respectively, as they may be a deserialized object. In case
an object was deserialized in a world with elevated privileges we also check the cached value is from the same
world, if it is from a different world we recompute it. For testing purposes, I added a new function to Internals
that determines whether a JSObject originated in the current world.

* CMakeLists.txt:
* WebCore.xcodeproj/project.pbxproj:
* bindings/js/DOMWrapperWorld.h:
(WebCore::worldForDOMObject):
* bindings/js/JSBindingsAllInOne.cpp:
* bindings/js/JSCustomEventCustom.cpp: Copied from Source/WebCore/dom/CustomEvent.cpp.
(WebCore::JSCustomEvent::detail):
* bindings/js/JSMessageEventCustom.cpp:
(WebCore::JSMessageEvent::data):
* bindings/js/JSPopStateEventCustom.cpp:
(WebCore::JSPopStateEvent::state):
* dom/CustomEvent.cpp:
(WebCore::CustomEvent::initCustomEvent):
(WebCore::CustomEvent::trySerializeDetail):
* dom/CustomEvent.h:
* dom/CustomEvent.idl:
* dom/MessageEvent.cpp:
(WebCore::MessageEvent::initMessageEvent):
(WebCore::MessageEvent::trySerializeData):
* dom/MessageEvent.h:
* dom/PopStateEvent.cpp:
(WebCore::PopStateEvent::trySerializeState):
* dom/PopStateEvent.h:
* testing/Internals.cpp:
(WebCore::Internals::isFromCurrentWorld):
* testing/Internals.h:
* testing/Internals.idl:

LayoutTests:

These tests ensure ensure objects are not leaked across isolated worlds and that those properties are not prematurely
garbage collected.

* fast/events/constructors/custom-event-constructor-expected.txt:
* fast/events/constructors/custom-event-constructor.html:
* fast/events/event-leak-objects-expected.txt: Added.
* fast/events/event-leak-objects.html: Added.
* fast/events/event-properties-gc-expected.txt: Added.
* fast/events/event-properties-gc.html: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsfasteventsconstructorscustomeventconstructorexpectedtxt">trunk/LayoutTests/fast/events/constructors/custom-event-constructor-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfasteventsconstructorscustomeventconstructorhtml">trunk/LayoutTests/fast/events/constructors/custom-event-constructor.html</a></li>
<li><a href="#trunkLayoutTestsfasteventseventleakobjectsexpectedtxt">trunk/LayoutTests/fast/events/event-leak-objects-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfasteventseventleakobjectshtml">trunk/LayoutTests/fast/events/event-leak-objects.html</a></li>
<li><a href="#trunkLayoutTestsfasteventseventpropertiesgcexpectedtxt">trunk/LayoutTests/fast/events/event-properties-gc-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfasteventseventpropertiesgchtml">trunk/LayoutTests/fast/events/event-properties-gc.html</a></li>
<li><a href="#trunkSourceWebCoreCMakeListstxt">trunk/Source/WebCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreWebCorexcodeprojprojectpbxproj">trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWebCorebindingsjsDOMWrapperWorldh">trunk/Source/WebCore/bindings/js/DOMWrapperWorld.h</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSBindingsAllInOnecpp">trunk/Source/WebCore/bindings/js/JSBindingsAllInOne.cpp</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSCustomEventCustomcpp">trunk/Source/WebCore/bindings/js/JSCustomEventCustom.cpp</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSMessageEventCustomcpp">trunk/Source/WebCore/bindings/js/JSMessageEventCustom.cpp</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSPopStateEventCustomcpp">trunk/Source/WebCore/bindings/js/JSPopStateEventCustom.cpp</a></li>
<li><a href="#trunkSourceWebCoredomCustomEventcpp">trunk/Source/WebCore/dom/CustomEvent.cpp</a></li>
<li><a href="#trunkSourceWebCoredomCustomEventh">trunk/Source/WebCore/dom/CustomEvent.h</a></li>
<li><a href="#trunkSourceWebCoredomCustomEventidl">trunk/Source/WebCore/dom/CustomEvent.idl</a></li>
<li><a href="#trunkSourceWebCoredomMessageEventcpp">trunk/Source/WebCore/dom/MessageEvent.cpp</a></li>
<li><a href="#trunkSourceWebCoredomMessageEventh">trunk/Source/WebCore/dom/MessageEvent.h</a></li>
<li><a href="#trunkSourceWebCoredomPopStateEventcpp">trunk/Source/WebCore/dom/PopStateEvent.cpp</a></li>
<li><a href="#trunkSourceWebCoredomPopStateEventh">trunk/Source/WebCore/dom/PopStateEvent.h</a></li>
<li><a href="#trunkSourceWebCoretestingInternalscpp">trunk/Source/WebCore/testing/Internals.cpp</a></li>
<li><a href="#trunkSourceWebCoretestingInternalsh">trunk/Source/WebCore/testing/Internals.h</a></li>
<li><a href="#trunkSourceWebCoretestingInternalsidl">trunk/Source/WebCore/testing/Internals.idl</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (186954 => 186955)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2015-07-17 09:23:28 UTC (rev 186954)
+++ trunk/LayoutTests/ChangeLog        2015-07-17 18:11:40 UTC (rev 186955)
</span><span class="lines">@@ -1,3 +1,21 @@
</span><ins>+2015-07-16  Mark Lam  &lt;mark.lam@apple.com&gt;
+
+        Remove leak of objects between isolated worlds on custom events, message events, and pop state events.
+        https://bugs.webkit.org/show_bug.cgi?id=118884
+
+        Reviewed by Filip Pizlo and Mark Lam.
+        Patch by Keith Miller  &lt;keith_miller@apple.com&gt;.
+
+        These tests ensure ensure objects are not leaked across isolated worlds and that those properties are not prematurely
+        garbage collected.
+
+        * fast/events/constructors/custom-event-constructor-expected.txt:
+        * fast/events/constructors/custom-event-constructor.html:
+        * fast/events/event-leak-objects-expected.txt: Added.
+        * fast/events/event-leak-objects.html: Added.
+        * fast/events/event-properties-gc-expected.txt: Added.
+        * fast/events/event-properties-gc.html: Added.
+
</ins><span class="cx"> 2015-07-16  Simon Fraser  &lt;simon.fraser@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Fix disappearing position:fixed elements in fixed layout mode
</span></span></pre></div>
<a id="trunkLayoutTestsfasteventsconstructorscustomeventconstructorexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/events/constructors/custom-event-constructor-expected.txt (186954 => 186955)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/events/constructors/custom-event-constructor-expected.txt        2015-07-17 09:23:28 UTC (rev 186954)
+++ trunk/LayoutTests/fast/events/constructors/custom-event-constructor-expected.txt        2015-07-17 18:11:40 UTC (rev 186955)
</span><span class="lines">@@ -13,8 +13,11 @@
</span><span class="cx"> PASS new CustomEvent('eventType', { detail: 'string' }).detail is 'string'
</span><span class="cx"> PASS new CustomEvent('eventType', { detail: detailObject }).detail is detailObject
</span><span class="cx"> PASS new CustomEvent('eventType', { detail: document }).detail is document
</span><ins>+PASS new CustomEvent('eventType', { detail: undefined }).detail is undefined
+PASS new CustomEvent('eventType', { detail: null }).detail is null
</ins><span class="cx"> PASS new CustomEvent('eventType', { get detail() { return true; } }).detail is true
</span><span class="cx"> PASS new CustomEvent('eventType', { get detail() { throw 'Custom Error'; } }) threw exception Custom Error.
</span><ins>+PASS event.detail is detailObject
</ins><span class="cx"> PASS successfullyParsed is true
</span><span class="cx"> 
</span><span class="cx"> TEST COMPLETE
</span></span></pre></div>
<a id="trunkLayoutTestsfasteventsconstructorscustomeventconstructorhtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/events/constructors/custom-event-constructor.html (186954 => 186955)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/events/constructors/custom-event-constructor.html        2015-07-17 09:23:28 UTC (rev 186954)
+++ trunk/LayoutTests/fast/events/constructors/custom-event-constructor.html        2015-07-17 18:11:40 UTC (rev 186955)
</span><span class="lines">@@ -31,11 +31,23 @@
</span><span class="cx"> // Detail is a DOM object
</span><span class="cx"> shouldBe(&quot;new CustomEvent('eventType', { detail: document }).detail&quot;, &quot;document&quot;);
</span><span class="cx"> 
</span><ins>+// Detail is undefined.
+shouldBe(&quot;new CustomEvent('eventType', { detail: undefined }).detail&quot;, &quot;undefined&quot;);
+
+// Detail is null.
+shouldBe(&quot;new CustomEvent('eventType', { detail: null }).detail&quot;, &quot;null&quot;);
+
</ins><span class="cx"> // Detail is a getter.
</span><span class="cx"> shouldBe(&quot;new CustomEvent('eventType', { get detail() { return true; } }).detail&quot;, &quot;true&quot;);
</span><span class="cx"> 
</span><span class="cx"> // Detail throws an exeception.
</span><span class="cx"> shouldThrow(&quot;new CustomEvent('eventType', { get detail() { throw 'Custom Error'; } })&quot;);
</span><ins>+
+// try initCustomEvent
+var event = document.createEvent('CustomEvent');
+event.initCustomEvent('eventType', true, false, detailObject);
+shouldBe(&quot;event.detail&quot;, &quot;detailObject&quot;);
+
</ins><span class="cx"> &lt;/script&gt;
</span><span class="cx"> &lt;script src=&quot;../../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
</span><span class="cx"> &lt;/body&gt;
</span></span></pre></div>
<a id="trunkLayoutTestsfasteventseventleakobjectsexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/events/event-leak-objects-expected.txt (186954 => 186955)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/events/event-leak-objects-expected.txt        2015-07-17 09:23:28 UTC (rev 186954)
+++ trunk/LayoutTests/fast/events/event-leak-objects-expected.txt        2015-07-17 18:11:40 UTC (rev 186955)
</span><span class="lines">@@ -0,0 +1,58 @@
</span><ins>+PASS window.internals.isFromCurrentWorld(event) is true
+PASS checkAllPropertiesFromCurrentWorld(resultValue) is true
+PASS Object.pageDefinedVar is undefined.
+PASS window.internals.isFromCurrentWorld(event) is true
+PASS checkAllPropertiesFromCurrentWorld(resultValue) is true
+PASS Object.pageDefinedVar is undefined.
+PASS window.internals.isFromCurrentWorld(event) is true
+PASS checkAllPropertiesFromCurrentWorld(resultValue) is true
+PASS Object.pageDefinedVar is undefined.
+PASS window.internals.isFromCurrentWorld(event) is true
+PASS checkAllPropertiesFromCurrentWorld(resultValue) is true
+PASS Object.pageDefinedVar is undefined.
+PASS window.internals.isFromCurrentWorld(event) is true
+PASS checkAllPropertiesFromCurrentWorld(resultValue) is true
+PASS Object.pageDefinedVar is undefined.
+PASS window.internals.isFromCurrentWorld(event) is true
+PASS checkAllPropertiesFromCurrentWorld(resultValue) is true
+PASS Object.pageDefinedVar is undefined.
+PASS window.internals.isFromCurrentWorld(event) is true
+PASS checkAllPropertiesFromCurrentWorld(resultValue) is true
+PASS Object.pageDefinedVar is undefined.
+PASS window.internals.isFromCurrentWorld(event) is true
+PASS checkAllPropertiesFromCurrentWorld(resultValue) is true
+PASS Object.pageDefinedVar is undefined.
+PASS window.internals.isFromCurrentWorld(event) is true
+PASS checkAllPropertiesFromCurrentWorld(resultValue) is true
+PASS Object.pageDefinedVar is undefined.
+PASS window.internals.isFromCurrentWorld(event) is true
+PASS checkAllPropertiesFromCurrentWorld(resultValue) is true
+PASS Object.pageDefinedVar is undefined.
+PASS window.internals.isFromCurrentWorld(event) is true
+PASS checkAllPropertiesFromCurrentWorld(resultValue) is true
+PASS Object.pageDefinedVar is undefined.
+PASS window.internals.isFromCurrentWorld(event) is true
+PASS checkAllPropertiesFromCurrentWorld(resultValue) is true
+PASS Object.pageDefinedVar is undefined.
+PASS window.internals.isFromCurrentWorld(event) is true
+PASS checkAllPropertiesFromCurrentWorld(resultValue) is true
+PASS Object.pageDefinedVar is undefined.
+PASS window.internals.isFromCurrentWorld(event) is true
+PASS checkAllPropertiesFromCurrentWorld(resultValue) is true
+PASS Object.pageDefinedVar is undefined.
+PASS window.internals.isFromCurrentWorld(event) is true
+PASS checkAllPropertiesFromCurrentWorld(resultValue) is true
+PASS Object.pageDefinedVar is undefined.
+PASS window.internals.isFromCurrentWorld(event) is true
+PASS checkAllPropertiesFromCurrentWorld(resultValue) is true
+PASS Object.pageDefinedVar is undefined.
+PASS window.internals.isFromCurrentWorld(event) is true
+PASS checkAllPropertiesFromCurrentWorld(resultValue) is true
+PASS Object.pageDefinedVar is undefined.
+PASS window.internals.isFromCurrentWorld(event) is true
+PASS checkAllPropertiesFromCurrentWorld(resultValue) is true
+PASS Object.pageDefinedVar is undefined.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfasteventseventleakobjectshtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/events/event-leak-objects.html (186954 => 186955)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/events/event-leak-objects.html        2015-07-17 09:23:28 UTC (rev 186954)
+++ trunk/LayoutTests/fast/events/event-leak-objects.html        2015-07-17 18:11:40 UTC (rev 186955)
</span><span class="lines">@@ -0,0 +1,122 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;script&gt;
+window.jsTestIsAsync = true;
+
+// The events that we want to test, with the properties that each one uses.
+var events = [
+    { eventKind: &quot;CustomEvent&quot;, propName: &quot;detail&quot; },
+    { eventKind: &quot;MessageEvent&quot;, propName: &quot;data&quot;  },
+    { eventKind: &quot;PopStateEvent&quot;, propName: &quot;state&quot; }
+];
+
+// Types we can put in the property of the Event
+var values = [
+    { propValue: &quot;document&quot; },
+    { propValue: '{&quot;bar&quot;:1}' },
+    { propValue: &quot;5&quot; },
+    { propValue: '&quot;hello&quot;' },
+    { propValue: &quot;true&quot; },
+    { propValue: &quot;[1,2,3]&quot; }
+];
+
+function merge(obj1, obj2) {
+    var newObj = { };
+    for (var attrname in obj1) { newObj[attrname] = obj1[attrname]; }
+    for (var attrname in obj2) { newObj[attrname] = obj2[attrname]; }
+    return newObj;
+}
+
+// Format the tests so they look like [ { eventKind: ..., propValue: ... }, ... { eventKind: ..., propValue: ... } ]
+var tests = events.map(function(event) {
+    return values.map(function(value) {
+        return merge(event, value);
+    })
+});
+tests = tests.reduce(function(a, b) {
+    return a.concat(b);
+});
+
+// We need to scan all the properies of value to ensure they all came from the current world.
+// Assumes window.internals exists.
+function checkAllPropertiesFromCurrentWorld(value) {
+    var allFromCurrentWorld = true;
+    while (allFromCurrentWorld &amp;&amp; value &amp;&amp; typeof value === &quot;object&quot;) {
+        allFromCurrentWorld = allFromCurrentWorld &amp;&amp; window.internals.isFromCurrentWorld(value);
+        for (var prop in value)
+            allFromCurrentWorld = allFromCurrentWorld &amp;&amp; checkAllPropertiesFromCurrentWorld(value[prop], seenValues);
+        value = Object.getPrototypeOf(value);
+    }
+
+    return allFromCurrentWorld;
+}
+
+function addListener(eventKind, eventString, prop) {
+    document.addEventListener(eventString, function(event) {
+        eventValue = event
+        resultValue = event[prop]
+
+        if (window.internals) {
+            shouldBeTrue(&quot;window.internals.isFromCurrentWorld(event)&quot;);
+            shouldBeTrue(&quot;checkAllPropertiesFromCurrentWorld(resultValue)&quot;);
+        }
+
+        // The property defined in the isolated world should be undefined.
+        shouldBeUndefined(&quot;Object.pageDefinedVar&quot;);
+        window.postMessage(&quot;done&quot;, &quot;*&quot;);
+    });
+}
+
+function sendDocumentEvent(eventKind, eventString, prop, value) {
+    var constructor = eval(eventKind);
+    var initializer = { };
+    initializer[prop] = value;
+    var newEvent = new constructor(eventString, initializer);
+    // Try to access the property in a different world to make sure caching issues do not occur
+    newEvent[prop];
+    document.dispatchEvent(newEvent);
+}
+
+function runScript(eventKind, propName, propValue, number) {
+    // Final string should have the form:
+    //     document.pageDefinedVar = 1; (function sendDocumentObject(eventKind, propName, result) {...})(...);
+    // When evaluated in the isolated world, should initiate the event with the
+    // document object as the specificed property value.
+    var eventString = eventKind + number;
+
+    var script = &quot;Object.pageDefinedVar = 1; &quot;
+        + &quot;(&quot; + sendDocumentEvent.toString() + &quot;)('&quot;
+        + eventKind + &quot;', '&quot; + eventString + &quot;', '&quot; + propName + &quot;', &quot; + propValue + &quot;);&quot;;
+    addListener(eventKind, eventString);
+    testRunner.evaluateScriptInIsolatedWorld(0, script);
+}
+
+// Run the tests whenever a notification arrives, which indicates that the
+// previous test has finished.
+window.addEventListener(&quot;message&quot;, function(message) {
+    runNextTest();
+}, false);
+
+// Keep a count to make a unique string
+var count = 1;
+function runNextTest () {
+    var test = tests.pop();
+    if (!test) {
+        finishJSTest();
+        return;
+    }
+    runScript(test.eventKind, test.propName, test.propValue, count++);
+};
+
+// This test is meaningless without testRunner.
+if (window.testRunner) {
+    runNextTest();
+}
+&lt;/script&gt;
+&lt;/body&gt;
+&lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsfasteventseventpropertiesgcexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/events/event-properties-gc-expected.txt (186954 => 186955)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/events/event-properties-gc-expected.txt        2015-07-17 09:23:28 UTC (rev 186954)
+++ trunk/LayoutTests/fast/events/event-properties-gc-expected.txt        2015-07-17 18:11:40 UTC (rev 186955)
</span><span class="lines">@@ -0,0 +1,7 @@
</span><ins>+PASS event[prop] is &quot;foo&quot;
+PASS event[prop] is &quot;foo&quot;
+PASS event[prop] is &quot;foo&quot;
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfasteventseventpropertiesgchtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/events/event-properties-gc.html (186954 => 186955)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/events/event-properties-gc.html        2015-07-17 09:23:28 UTC (rev 186954)
+++ trunk/LayoutTests/fast/events/event-properties-gc.html        2015-07-17 18:11:40 UTC (rev 186955)
</span><span class="lines">@@ -0,0 +1,60 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;script&gt;
+window.jsTestIsAsync = true;
+
+function addListener(eventType, prop) {
+    document.addEventListener(eventType, function(event) {
+        window.prop = prop;
+        // Despite the earlier assignement of the local variable to null and
+        // the following garabage collection, the property should still be
+        // present here.
+        shouldBeEqualToString(&quot;event[prop]&quot;, &quot;foo&quot;);
+        window.prop = undefined;
+        window.postMessage(&quot;done&quot;, &quot;*&quot;);
+    });
+}
+
+// Run the tests whenever a notification arrives, which indicates that the
+// previous test has finished.
+window.addEventListener(&quot;message&quot;, function(message) {
+    runNextTest();
+}, false);
+
+function newEvent(eventType, prop, value) {
+   return eval(&quot;new &quot; + eventType + &quot;('&quot; + eventType + &quot;', { &quot; + prop + &quot;: value })&quot;);
+}
+
+// The events that we want to test, with the properties that each one uses.
+var events = [
+    { eventType: &quot;CustomEvent&quot;, prop: &quot;detail&quot; },
+    { eventType: &quot;MessageEvent&quot;, prop: &quot;data&quot; },
+    { eventType: &quot;PopStateEvent&quot;, prop: &quot;state&quot; }
+];
+
+function runNextTest () {
+    var evt = events.pop();
+    if (!evt) {
+        finishJSTest();
+        return;
+    }
+    var value = &quot;foo&quot;;
+    var eventToDispatch = newEvent(evt.eventType, evt.prop, value);
+    value = null;
+    gc();
+    addListener(evt.eventType, evt.prop);
+    document.dispatchEvent(eventToDispatch);
+};
+
+// This test is meaningless without testRunner.
+if (window.testRunner) {
+    runNextTest();
+}
+&lt;/script&gt;
+&lt;/body&gt;
+&lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkSourceWebCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/CMakeLists.txt (186954 => 186955)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/CMakeLists.txt        2015-07-17 09:23:28 UTC (rev 186954)
+++ trunk/Source/WebCore/CMakeLists.txt        2015-07-17 18:11:40 UTC (rev 186955)
</span><span class="lines">@@ -1097,6 +1097,7 @@
</span><span class="cx">     bindings/js/JSCryptoKeyPairCustom.cpp
</span><span class="cx">     bindings/js/JSCryptoKeySerializationJWK.cpp
</span><span class="cx">     bindings/js/JSCryptoOperationData.cpp
</span><ins>+    bindings/js/JSCustomEventCustom.cpp
</ins><span class="cx">     bindings/js/JSCustomSQLStatementErrorCallback.cpp
</span><span class="cx">     bindings/js/JSCustomXPathNSResolver.cpp
</span><span class="cx">     bindings/js/JSDOMBinding.cpp
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (186954 => 186955)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2015-07-17 09:23:28 UTC (rev 186954)
+++ trunk/Source/WebCore/ChangeLog        2015-07-17 18:11:40 UTC (rev 186955)
</span><span class="lines">@@ -1,3 +1,50 @@
</span><ins>+2015-07-17  Mark Lam  &lt;mark.lam@apple.com&gt;
+
+        Remove leak of objects between isolated worlds on custom events, message events, and pop state events.
+        https://bugs.webkit.org/show_bug.cgi?id=118884
+
+        Reviewed by Filip Pizlo and Mark Lam.
+        Patch by Keith Miller  &lt;keith_miller@apple.com&gt;.
+
+        Tests: fast/events/event-leak-objects.html
+               fast/events/event-properties-gc.html
+
+        Fixes an issue where objects passed as certain properties of events could cross isolated worlds. This
+        was fixed by checking that any object passed by an event must be serializable or originate from the same
+        isolated world as the one it is currently being accessed in. In the case of MessageEvents and PopStateEvents we
+        cache the values of the data and state properties, respectively, as they may be a deserialized object. In case
+        an object was deserialized in a world with elevated privileges we also check the cached value is from the same
+        world, if it is from a different world we recompute it. For testing purposes, I added a new function to Internals
+        that determines whether a JSObject originated in the current world.
+
+        * CMakeLists.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * bindings/js/DOMWrapperWorld.h:
+        (WebCore::worldForDOMObject):
+        * bindings/js/JSBindingsAllInOne.cpp:
+        * bindings/js/JSCustomEventCustom.cpp: Copied from Source/WebCore/dom/CustomEvent.cpp.
+        (WebCore::JSCustomEvent::detail):
+        * bindings/js/JSMessageEventCustom.cpp:
+        (WebCore::JSMessageEvent::data):
+        * bindings/js/JSPopStateEventCustom.cpp:
+        (WebCore::JSPopStateEvent::state):
+        * dom/CustomEvent.cpp:
+        (WebCore::CustomEvent::initCustomEvent):
+        (WebCore::CustomEvent::trySerializeDetail):
+        * dom/CustomEvent.h:
+        * dom/CustomEvent.idl:
+        * dom/MessageEvent.cpp:
+        (WebCore::MessageEvent::initMessageEvent):
+        (WebCore::MessageEvent::trySerializeData):
+        * dom/MessageEvent.h:
+        * dom/PopStateEvent.cpp:
+        (WebCore::PopStateEvent::trySerializeState):
+        * dom/PopStateEvent.h:
+        * testing/Internals.cpp:
+        (WebCore::Internals::isFromCurrentWorld):
+        * testing/Internals.h:
+        * testing/Internals.idl:
+
</ins><span class="cx"> 2015-07-17  Carlos Garcia Campos  &lt;cgarcia@igalia.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [GTK] Cleanup PasteboardHelper
</span></span></pre></div>
<a id="trunkSourceWebCoreWebCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (186954 => 186955)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2015-07-17 09:23:28 UTC (rev 186954)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2015-07-17 18:11:40 UTC (rev 186955)
</span><span class="lines">@@ -6042,6 +6042,7 @@
</span><span class="cx">                 DEBCCDD216646E8200A452E1 /* RenderMediaControlElements.h in Headers */ = {isa = PBXBuildFile; fileRef = DE49B308165F2FE10010338D /* RenderMediaControlElements.h */; };
</span><span class="cx">                 DEBCCDD416646EAF00A452E1 /* MediaControlElementTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = DE49B300165F2FC60010338D /* MediaControlElementTypes.h */; };
</span><span class="cx">                 DEBCCDD516646EB200A452E1 /* MediaControlElementTypes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE49B2FF165F2FC60010338D /* MediaControlElementTypes.cpp */; };
</span><ins>+                DEC297611B4F2F8D005F5945 /* JSCustomEventCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEC2975D1B4DEB2A005F5945 /* JSCustomEventCustom.cpp */; };
</ins><span class="cx">                 DF9AFD7213FC31D80015FEB7 /* MediaPlayerPrivateAVFoundationObjC.h in Headers */ = {isa = PBXBuildFile; fileRef = DF9AFD7013FC31D80015FEB7 /* MediaPlayerPrivateAVFoundationObjC.h */; };
</span><span class="cx">                 DF9AFD7313FC31D80015FEB7 /* MediaPlayerPrivateAVFoundationObjC.mm in Sources */ = {isa = PBXBuildFile; fileRef = DF9AFD7113FC31D80015FEB7 /* MediaPlayerPrivateAVFoundationObjC.mm */; };
</span><span class="cx">                 E0FEF372B17C53EAC1C1FBEE /* EventSource.h in Headers */ = {isa = PBXBuildFile; fileRef = E0FEF371B17C53EAC1C1FBEE /* EventSource.h */; };
</span><span class="lines">@@ -13715,6 +13716,7 @@
</span><span class="cx">                 DE49B300165F2FC60010338D /* MediaControlElementTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaControlElementTypes.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 DE49B307165F2FE10010338D /* RenderMediaControlElements.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderMediaControlElements.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 DE49B308165F2FE10010338D /* RenderMediaControlElements.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderMediaControlElements.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                DEC2975D1B4DEB2A005F5945 /* JSCustomEventCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCustomEventCustom.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 DF9AFD7013FC31D80015FEB7 /* MediaPlayerPrivateAVFoundationObjC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaPlayerPrivateAVFoundationObjC.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 DF9AFD7113FC31D80015FEB7 /* MediaPlayerPrivateAVFoundationObjC.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MediaPlayerPrivateAVFoundationObjC.mm; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 E0FEF371B07C53EAC1C1FBEE /* EventSource.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = EventSource.idl; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -21414,6 +21416,7 @@
</span><span class="cx">                 BC4EDEF70C08F414007EDD49 /* Custom */ = {
</span><span class="cx">                         isa = PBXGroup;
</span><span class="cx">                         children = (
</span><ins>+                                DEC2975D1B4DEB2A005F5945 /* JSCustomEventCustom.cpp */,
</ins><span class="cx">                                 BC2ED6BB0C6BD2F000920BFF /* JSAttrCustom.cpp */,
</span><span class="cx">                                 FDEAAAEF12B02EE400DCF33B /* JSAudioBufferSourceNodeCustom.cpp */,
</span><span class="cx">                                 FDEAAAF012B02EE400DCF33B /* JSAudioContextCustom.cpp */,
</span><span class="lines">@@ -30400,6 +30403,7 @@
</span><span class="cx">                                 B2227AD90D00BF220071B782 /* SVGTransformable.cpp in Sources */,
</span><span class="cx">                                 B2227ADC0D00BF220071B782 /* SVGTransformDistance.cpp in Sources */,
</span><span class="cx">                                 B2227ADE0D00BF220071B782 /* SVGTransformList.cpp in Sources */,
</span><ins>+                                DEC297611B4F2F8D005F5945 /* JSCustomEventCustom.cpp in Sources */,
</ins><span class="cx">                                 B2227AE10D00BF220071B782 /* SVGTRefElement.cpp in Sources */,
</span><span class="cx">                                 B2227AE40D00BF220071B782 /* SVGTSpanElement.cpp in Sources */,
</span><span class="cx">                                 B2227AE90D00BF220071B782 /* SVGURIReference.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsDOMWrapperWorldh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/DOMWrapperWorld.h (186954 => 186955)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/DOMWrapperWorld.h        2015-07-17 09:23:28 UTC (rev 186954)
+++ trunk/Source/WebCore/bindings/js/DOMWrapperWorld.h        2015-07-17 18:11:40 UTC (rev 186955)
</span><span class="lines">@@ -74,6 +74,11 @@
</span><span class="cx">     return JSC::jsCast&lt;JSDOMGlobalObject*&gt;(exec-&gt;lexicalGlobalObject())-&gt;world();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+inline DOMWrapperWorld&amp; worldForDOMObject(JSC::JSObject* object)
+{
+    return JSC::jsCast&lt;JSDOMGlobalObject*&gt;(object-&gt;globalObject())-&gt;world();
+}
+    
</ins><span class="cx"> } // namespace WebCore
</span><span class="cx"> 
</span><span class="cx"> #endif // DOMWrapperWorld_h
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSBindingsAllInOnecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSBindingsAllInOne.cpp (186954 => 186955)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSBindingsAllInOne.cpp        2015-07-17 09:23:28 UTC (rev 186954)
+++ trunk/Source/WebCore/bindings/js/JSBindingsAllInOne.cpp        2015-07-17 18:11:40 UTC (rev 186955)
</span><span class="lines">@@ -45,6 +45,7 @@
</span><span class="cx"> #include &quot;JSCharacterDataCustom.cpp&quot;
</span><span class="cx"> #include &quot;JSCommandLineAPIHostCustom.cpp&quot;
</span><span class="cx"> #include &quot;JSCryptoCustom.cpp&quot;
</span><ins>+#include &quot;JSCustomEventCustom.cpp&quot;
</ins><span class="cx"> #include &quot;JSCustomSQLStatementErrorCallback.cpp&quot;
</span><span class="cx"> #include &quot;JSCustomXPathNSResolver.cpp&quot;
</span><span class="cx"> #include &quot;JSDOMBinding.cpp&quot;
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSCustomEventCustomcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSCustomEventCustom.cpp (186954 => 186955)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSCustomEventCustom.cpp        2015-07-17 09:23:28 UTC (rev 186954)
+++ trunk/Source/WebCore/bindings/js/JSCustomEventCustom.cpp        2015-07-17 18:11:40 UTC (rev 186955)
</span><span class="lines">@@ -0,0 +1,63 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include &quot;config.h&quot;
+#include &quot;JSCustomEvent.h&quot;
+
+#include &quot;CustomEvent.h&quot;
+#include &quot;DOMWrapperWorld.h&quot;
+#include &lt;runtime/JSCInlines.h&gt;
+#include &lt;runtime/JSCJSValue.h&gt;
+#include &lt;runtime/Structure.h&gt;
+
+using namespace JSC;
+
+namespace WebCore {
+    
+JSValue JSCustomEvent::detail(ExecState* exec) const
+{
+    CustomEvent&amp; event = impl();
+    
+    if (event.detail().hasNoValue())
+        return jsNull();
+
+    JSValue detail = event.detail().jsValue();
+    
+    if (detail.isObject() &amp;&amp; &amp;worldForDOMObject(detail.getObject()) != &amp;currentWorld(exec)) {
+        // We need to make sure CustomEvents do not leak their detail property across isolated DOM worlds.
+        // Ideally, we would check that the worlds have different privileges but that's not possible yet.
+        RefPtr&lt;SerializedScriptValue&gt; serializedDetail = event.trySerializeDetail(exec);
+        
+        if (!serializedDetail)
+            return jsNull();
+        
+        return serializedDetail-&gt;deserialize(exec, globalObject(), nullptr);
+    }
+    
+    return detail;
+}
+
+} // namespace WebCore
+
</ins></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSMessageEventCustomcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSMessageEventCustom.cpp (186954 => 186955)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSMessageEventCustom.cpp        2015-07-17 09:23:28 UTC (rev 186954)
+++ trunk/Source/WebCore/bindings/js/JSMessageEventCustom.cpp        2015-07-17 18:11:40 UTC (rev 186955)
</span><span class="lines">@@ -46,8 +46,12 @@
</span><span class="cx"> 
</span><span class="cx"> JSValue JSMessageEvent::data(ExecState* exec) const
</span><span class="cx"> {
</span><del>-    if (JSValue cachedValue = m_data.get())
-        return cachedValue;
</del><ins>+    if (JSValue cachedValue = m_data.get()) {
+        // We cannot use a cached object if we are in a different world than the one it was created in.
+        if (!cachedValue.isObject() || &amp;worldForDOMObject(cachedValue.getObject()) == &amp;currentWorld(exec))
+            return cachedValue;
+        ASSERT_NOT_REACHED();
+    }
</ins><span class="cx"> 
</span><span class="cx">     MessageEvent&amp; event = impl();
</span><span class="cx">     JSValue result;
</span><span class="lines">@@ -56,8 +60,19 @@
</span><span class="cx">         Deprecated::ScriptValue scriptValue = event.dataAsScriptValue();
</span><span class="cx">         if (scriptValue.hasNoValue())
</span><span class="cx">             result = jsNull();
</span><del>-        else
-            result = scriptValue.jsValue();
</del><ins>+        else {
+            JSValue dataValue = scriptValue.jsValue();
+            // We need to make sure MessageEvents do not leak objects in their state property across isolated DOM worlds.
+            // Ideally, we would check that the worlds have different privileges but that's not possible yet.
+            if (dataValue.isObject() &amp;&amp; &amp;worldForDOMObject(dataValue.getObject()) != &amp;currentWorld(exec)) {
+                RefPtr&lt;SerializedScriptValue&gt; serializedValue = event.trySerializeData(exec);
+                if (serializedValue)
+                    result = serializedValue-&gt;deserialize(exec, globalObject(), nullptr);
+                else
+                    result = jsNull();
+            } else
+                result = dataValue;
+        }
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSPopStateEventCustomcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSPopStateEventCustom.cpp (186954 => 186955)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSPopStateEventCustom.cpp        2015-07-17 09:23:28 UTC (rev 186954)
+++ trunk/Source/WebCore/bindings/js/JSPopStateEventCustom.cpp        2015-07-17 18:11:40 UTC (rev 186955)
</span><span class="lines">@@ -49,14 +49,29 @@
</span><span class="cx"> JSValue JSPopStateEvent::state(ExecState* exec) const
</span><span class="cx"> {
</span><span class="cx">     JSValue cachedValue = m_state.get();
</span><del>-    if (!cachedValue.isEmpty())
-        return cachedValue;
</del><ins>+    if (!cachedValue.isEmpty()) {
+        // We cannot use a cached object if we are in a different world than the one it was created in.
+        if (!cachedValue.isObject() || &amp;worldForDOMObject(cachedValue.getObject()) == &amp;currentWorld(exec))
+            return cachedValue;
+        ASSERT_NOT_REACHED();
+    }
</ins><span class="cx"> 
</span><span class="cx">     PopStateEvent&amp; event = impl();
</span><span class="cx"> 
</span><del>-    if (!event.state().hasNoValue())
-        return cacheState(exec, const_cast&lt;JSPopStateEvent*&gt;(this), event.state().jsValue());
-
</del><ins>+    if (!event.state().hasNoValue()) {
+        // We need to make sure a PopStateEvent does not leak objects in its state property across isolated DOM worlds.
+        // Ideally, we would check that the worlds have different privileges but that's not possible yet.
+        JSValue state = event.state().jsValue();
+        if (state.isObject() &amp;&amp; &amp;worldForDOMObject(state.getObject()) != &amp;currentWorld(exec)) {
+            if (RefPtr&lt;SerializedScriptValue&gt; serializedValue = event.trySerializeState(exec))
+                state = serializedValue-&gt;deserialize(exec, globalObject(), nullptr);
+            else
+                state = jsNull();
+        }
+        
+        return cacheState(exec, const_cast&lt;JSPopStateEvent*&gt;(this), state);
+    }
+    
</ins><span class="cx">     History* history = event.history();
</span><span class="cx">     if (!history || !event.serializedState())
</span><span class="cx">         return cacheState(exec, const_cast&lt;JSPopStateEvent*&gt;(this), jsNull());
</span></span></pre></div>
<a id="trunkSourceWebCoredomCustomEventcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/CustomEvent.cpp (186954 => 186955)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/CustomEvent.cpp        2015-07-17 09:23:28 UTC (rev 186954)
+++ trunk/Source/WebCore/dom/CustomEvent.cpp        2015-07-17 18:11:40 UTC (rev 186955)
</span><span class="lines">@@ -51,15 +51,26 @@
</span><span class="cx"> 
</span><span class="cx"> void CustomEvent::initCustomEvent(const AtomicString&amp; type, bool canBubble, bool cancelable, const Deprecated::ScriptValue&amp; detail)
</span><span class="cx"> {
</span><del>-    ASSERT(!m_serializedScriptValue.get());
</del><span class="cx">     if (dispatched())
</span><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     initEvent(type, canBubble, cancelable);
</span><span class="cx"> 
</span><span class="cx">     m_detail = detail;
</span><ins>+    m_serializedDetail = nullptr;
+    m_triedToSerialize = false;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+RefPtr&lt;SerializedScriptValue&gt; CustomEvent::trySerializeDetail(JSC::ExecState* exec)
+{
+    if (!m_serializedDetail &amp;&amp; !m_triedToSerialize) {
+        m_serializedDetail = SerializedScriptValue::create(exec, m_detail.jsValue(), nullptr, nullptr, NonThrowing);
+        m_triedToSerialize = true;
+    }
+    
+    return m_serializedDetail;
+}
+
</ins><span class="cx"> EventInterface CustomEvent::eventInterface() const
</span><span class="cx"> {
</span><span class="cx">     return CustomEventInterfaceType;
</span></span></pre></div>
<a id="trunkSourceWebCoredomCustomEventh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/CustomEvent.h (186954 => 186955)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/CustomEvent.h        2015-07-17 09:23:28 UTC (rev 186954)
+++ trunk/Source/WebCore/dom/CustomEvent.h        2015-07-17 18:11:40 UTC (rev 186955)
</span><span class="lines">@@ -57,14 +57,16 @@
</span><span class="cx">     virtual EventInterface eventInterface() const override;
</span><span class="cx"> 
</span><span class="cx">     const Deprecated::ScriptValue&amp; detail() const { return m_detail; }
</span><del>-    PassRefPtr&lt;SerializedScriptValue&gt; serializedScriptValue() { return m_serializedScriptValue; }
</del><ins>+    
+    RefPtr&lt;SerializedScriptValue&gt; trySerializeDetail(JSC::ExecState*);
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     CustomEvent();
</span><span class="cx">     CustomEvent(const AtomicString&amp; type, const CustomEventInit&amp; initializer);
</span><span class="cx"> 
</span><span class="cx">     Deprecated::ScriptValue m_detail;
</span><del>-    RefPtr&lt;SerializedScriptValue&gt; m_serializedScriptValue;
</del><ins>+    RefPtr&lt;SerializedScriptValue&gt; m_serializedDetail;
+    bool m_triedToSerialize { false };
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoredomCustomEventidl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/CustomEvent.idl (186954 => 186955)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/CustomEvent.idl        2015-07-17 09:23:28 UTC (rev 186954)
+++ trunk/Source/WebCore/dom/CustomEvent.idl        2015-07-17 18:11:40 UTC (rev 186955)
</span><span class="lines">@@ -27,11 +27,11 @@
</span><span class="cx"> [
</span><span class="cx">     ConstructorTemplate=Event,
</span><span class="cx"> ] interface CustomEvent : Event {
</span><del>-    [InitializedByEventConstructor] readonly attribute any detail;
</del><ins>+    [InitializedByEventConstructor, CustomGetter] readonly attribute any detail;
</ins><span class="cx"> 
</span><del>-    void initCustomEvent([Default=Undefined] optional DOMString typeArg, 
-                         [Default=Undefined] optional boolean canBubbleArg, 
-                         [Default=Undefined] optional boolean cancelableArg, 
</del><ins>+    void initCustomEvent([Default=Undefined] optional DOMString typeArg,
+                         [Default=Undefined] optional boolean canBubbleArg,
+                         [Default=Undefined] optional boolean cancelableArg,
</ins><span class="cx">                          [Default=Undefined] optional any detailArg);
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoredomMessageEventcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/MessageEvent.cpp (186954 => 186955)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/MessageEvent.cpp        2015-07-17 09:23:28 UTC (rev 186954)
+++ trunk/Source/WebCore/dom/MessageEvent.cpp        2015-07-17 18:11:40 UTC (rev 186955)
</span><span class="lines">@@ -118,6 +118,8 @@
</span><span class="cx"> 
</span><span class="cx">     m_dataType = DataTypeScriptValue;
</span><span class="cx">     m_dataAsScriptValue = data;
</span><ins>+    m_dataAsSerializedScriptValue = nullptr;
+    m_triedToSerialize = false;
</ins><span class="cx">     m_origin = origin;
</span><span class="cx">     m_lastEventId = lastEventId;
</span><span class="cx">     m_source = source;
</span><span class="lines">@@ -138,6 +140,18 @@
</span><span class="cx">     m_source = source;
</span><span class="cx">     m_ports = WTF::move(ports);
</span><span class="cx"> }
</span><ins>+    
+RefPtr&lt;SerializedScriptValue&gt; MessageEvent::trySerializeData(JSC::ExecState* exec)
+{
+    ASSERT(!m_dataAsScriptValue.hasNoValue());
+    
+    if (!m_dataAsSerializedScriptValue &amp;&amp; !m_triedToSerialize) {
+        m_dataAsSerializedScriptValue = SerializedScriptValue::create(exec, m_dataAsScriptValue.jsValue(), nullptr, nullptr, NonThrowing);
+        m_triedToSerialize = true;
+    }
+    
+    return m_dataAsSerializedScriptValue;
+}
</ins><span class="cx"> 
</span><span class="cx"> // FIXME: Remove this when we have custom ObjC binding support.
</span><span class="cx"> SerializedScriptValue* MessageEvent::data() const
</span></span></pre></div>
<a id="trunkSourceWebCoredomMessageEventh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/MessageEvent.h (186954 => 186955)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/MessageEvent.h        2015-07-17 09:23:28 UTC (rev 186954)
+++ trunk/Source/WebCore/dom/MessageEvent.h        2015-07-17 18:11:40 UTC (rev 186955)
</span><span class="lines">@@ -114,6 +114,8 @@
</span><span class="cx">     Blob* dataAsBlob() const { ASSERT(m_dataType == DataTypeBlob); return m_dataAsBlob.get(); }
</span><span class="cx">     ArrayBuffer* dataAsArrayBuffer() const { ASSERT(m_dataType == DataTypeArrayBuffer); return m_dataAsArrayBuffer.get(); }
</span><span class="cx"> 
</span><ins>+    RefPtr&lt;SerializedScriptValue&gt; trySerializeData(JSC::ExecState*);
+    
</ins><span class="cx"> private:
</span><span class="cx">     MessageEvent();
</span><span class="cx">     MessageEvent(const AtomicString&amp;, const MessageEventInit&amp;);
</span><span class="lines">@@ -127,6 +129,7 @@
</span><span class="cx">     DataType m_dataType;
</span><span class="cx">     Deprecated::ScriptValue m_dataAsScriptValue;
</span><span class="cx">     RefPtr&lt;SerializedScriptValue&gt; m_dataAsSerializedScriptValue;
</span><ins>+    bool m_triedToSerialize { false };
</ins><span class="cx">     String m_dataAsString;
</span><span class="cx">     RefPtr&lt;Blob&gt; m_dataAsBlob;
</span><span class="cx">     RefPtr&lt;ArrayBuffer&gt; m_dataAsArrayBuffer;
</span></span></pre></div>
<a id="trunkSourceWebCoredomPopStateEventcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/PopStateEvent.cpp (186954 => 186955)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/PopStateEvent.cpp        2015-07-17 09:23:28 UTC (rev 186954)
+++ trunk/Source/WebCore/dom/PopStateEvent.cpp        2015-07-17 18:11:40 UTC (rev 186955)
</span><span class="lines">@@ -29,7 +29,6 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;EventNames.h&quot;
</span><span class="cx"> #include &quot;History.h&quot;
</span><del>-#include &quot;SerializedScriptValue.h&quot;
</del><span class="cx"> #include &lt;runtime/JSCInlines.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="lines">@@ -79,6 +78,18 @@
</span><span class="cx">     return adoptRef(*new PopStateEvent(type, initializer));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+RefPtr&lt;SerializedScriptValue&gt; PopStateEvent::trySerializeState(JSC::ExecState* exec)
+{
+    ASSERT(!m_state.hasNoValue());
+    
+    if (!m_serializedState &amp;&amp; !m_triedToSerialize) {
+        m_serializedState = SerializedScriptValue::create(exec, m_state.jsValue(), nullptr, nullptr, NonThrowing);
+        m_triedToSerialize = true;
+    }
+    
+    return m_serializedState;
+}
+
</ins><span class="cx"> EventInterface PopStateEvent::eventInterface() const
</span><span class="cx"> {
</span><span class="cx">     return PopStateEventInterfaceType;
</span></span></pre></div>
<a id="trunkSourceWebCoredomPopStateEventh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/PopStateEvent.h (186954 => 186955)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/PopStateEvent.h        2015-07-17 09:23:28 UTC (rev 186954)
+++ trunk/Source/WebCore/dom/PopStateEvent.h        2015-07-17 18:11:40 UTC (rev 186955)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> #define PopStateEvent_h
</span><span class="cx"> 
</span><span class="cx"> #include &quot;Event.h&quot;
</span><ins>+#include &quot;SerializedScriptValue.h&quot;
</ins><span class="cx"> #include &lt;bindings/ScriptValue.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="lines">@@ -48,7 +49,10 @@
</span><span class="cx">     static Ref&lt;PopStateEvent&gt; create(PassRefPtr&lt;SerializedScriptValue&gt;, PassRefPtr&lt;History&gt;);
</span><span class="cx">     static Ref&lt;PopStateEvent&gt; create(const AtomicString&amp;, const PopStateEventInit&amp;);
</span><span class="cx"> 
</span><del>-    PassRefPtr&lt;SerializedScriptValue&gt; serializedState() const { return m_serializedState; }
</del><ins>+    PassRefPtr&lt;SerializedScriptValue&gt; serializedState() const { ASSERT(m_serializedState); return m_serializedState; }
+    
+    RefPtr&lt;SerializedScriptValue&gt; trySerializeState(JSC::ExecState*);
+    
</ins><span class="cx">     const Deprecated::ScriptValue&amp; state() const { return m_state; }
</span><span class="cx">     History* history() const { return m_history.get(); }
</span><span class="cx"> 
</span><span class="lines">@@ -61,6 +65,7 @@
</span><span class="cx"> 
</span><span class="cx">     Deprecated::ScriptValue m_state;
</span><span class="cx">     RefPtr&lt;SerializedScriptValue&gt; m_serializedState;
</span><ins>+    bool m_triedToSerialize { false };
</ins><span class="cx">     RefPtr&lt;History&gt; m_history;
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoretestingInternalscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/testing/Internals.cpp (186954 => 186955)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/testing/Internals.cpp        2015-07-17 09:23:28 UTC (rev 186954)
+++ trunk/Source/WebCore/testing/Internals.cpp        2015-07-17 18:11:40 UTC (rev 186955)
</span><span class="lines">@@ -2357,6 +2357,16 @@
</span><span class="cx">     return SerializedScriptValue::adopt(bytes);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool Internals::isFromCurrentWorld(Deprecated::ScriptValue value) const
+{
+    ASSERT(!value.hasNoValue());
+    
+    JSC::ExecState* exec = contextDocument()-&gt;vm().topCallFrame;
+    if (!value.isObject() || &amp;worldForDOMObject(value.jsValue().getObject()) == &amp;currentWorld(exec))
+        return true;
+    return false;
+}
+
</ins><span class="cx"> void Internals::setUsesOverlayScrollbars(bool enabled)
</span><span class="cx"> {
</span><span class="cx">     WebCore::Settings::setUsesOverlayScrollbars(enabled);
</span></span></pre></div>
<a id="trunkSourceWebCoretestingInternalsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/testing/Internals.h (186954 => 186955)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/testing/Internals.h        2015-07-17 09:23:28 UTC (rev 186954)
+++ trunk/Source/WebCore/testing/Internals.h        2015-07-17 18:11:40 UTC (rev 186955)
</span><span class="lines">@@ -324,6 +324,8 @@
</span><span class="cx">     PassRefPtr&lt;ArrayBuffer&gt; serializeObject(PassRefPtr&lt;SerializedScriptValue&gt;) const;
</span><span class="cx">     PassRefPtr&lt;SerializedScriptValue&gt; deserializeBuffer(PassRefPtr&lt;ArrayBuffer&gt;) const;
</span><span class="cx"> 
</span><ins>+    bool isFromCurrentWorld(Deprecated::ScriptValue) const;
+
</ins><span class="cx">     void setUsesOverlayScrollbars(bool enabled);
</span><span class="cx"> 
</span><span class="cx">     String getCurrentCursorInfo(ExceptionCode&amp;);
</span></span></pre></div>
<a id="trunkSourceWebCoretestingInternalsidl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/testing/Internals.idl (186954 => 186955)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/testing/Internals.idl        2015-07-17 09:23:28 UTC (rev 186954)
+++ trunk/Source/WebCore/testing/Internals.idl        2015-07-17 18:11:40 UTC (rev 186955)
</span><span class="lines">@@ -311,6 +311,8 @@
</span><span class="cx">     SerializedScriptValue deserializeBuffer(ArrayBuffer buffer);
</span><span class="cx">     ArrayBuffer serializeObject(SerializedScriptValue obj);
</span><span class="cx"> 
</span><ins>+    boolean isFromCurrentWorld(any obj);
+
</ins><span class="cx">     void setUsesOverlayScrollbars(boolean enabled);
</span><span class="cx"> 
</span><span class="cx">     void forceReload(boolean endToEnd);
</span></span></pre>
</div>
</div>

</body>
</html>