| Differences between
and this patch
- a/Source/WebCore/ChangeLog +48 lines
Lines 1-3 a/Source/WebCore/ChangeLog_sec1
1
2016-04-04  Chris Dumez  <cdumez@apple.com>
2
3
        MessageEvent.source window is incorrect once window has been reified
4
        https://bugs.webkit.org/show_bug.cgi?id=156227
5
        <rdar://problem/25545831>
6
7
        Reviewed by NOBODY (OOPS!).
8
9
        MessageEvent.source window was incorrect once window had been reified.
10
11
        If the Window had not been reified, we kept constructing new
12
        postMessage() functions when calling window.postMessage(). We used to
13
        pass activeDOMWindow(execState) as source Window to
14
        DOMWindow::postMessage(). activeDOMWindow() uses
15
        exec->lexicalGlobalObject() which did the right thing because we
16
        used to construct a new postMessage() function in the caller's context.
17
18
        However, after reification, due to the way JSDOMWindow::getOwnPropertySlot()
19
        was implemented, we would stop constructing new postMessage() functions
20
        when calling window.postMessage(). As a result, the source window would
21
        become incorrect because exec->lexicalGlobalObject() would return the
22
        target Window instead.
23
24
        In this patch, the following is done:
25
        1. Stop constructing a new function every time in the same origin case
26
           for postMessage, blur, focus and close. This was inefficient and lead
27
           to incorrect behavior:
28
           - The behavior would differ depending if the Window is reified or not
29
           - It would be impossible to delete those operations, which is
30
             incompatible with the specification and other browsers (tested
31
             Firefox and Chrome).
32
        2. Use callerDOMWindow(execState) instead of activeDOMWindow(execState)
33
           as source Window in JSDOMWindow::handlePostMessage(). callerDOMWindow()
34
           is a new utility function that returns the caller's Window object.
35
36
        Tests: fast/dom/Window/delete-operations.html
37
               fast/dom/Window/messageevent-source-postmessage-reified.html
38
               fast/dom/Window/messageevent-source-postmessage.html
39
               fast/dom/Window/window-postmessage-clone-frames.html
40
41
        * bindings/js/JSDOMBinding.cpp:
42
        (WebCore::GetCallerCodeBlockFunctor::operator()):
43
        (WebCore::GetCallerCodeBlockFunctor::codeBlock):
44
        (WebCore::callerDOMWindow):
45
        * bindings/js/JSDOMBinding.h:
46
        * bindings/js/JSDOMWindowCustom.cpp:
47
        (WebCore::handlePostMessage):
48
1
2016-04-04  Anders Carlsson  <andersca@apple.com>
49
2016-04-04  Anders Carlsson  <andersca@apple.com>
2
50
3
        Properly generate static functions that return Promises
51
        Properly generate static functions that return Promises
- a/Source/WebCore/bindings/js/JSDOMBinding.cpp +31 lines
Lines 35-40 a/Source/WebCore/bindings/js/JSDOMBinding.cpp_sec1
35
#include "JSDOMWindowCustom.h"
35
#include "JSDOMWindowCustom.h"
36
#include "JSExceptionBase.h"
36
#include "JSExceptionBase.h"
37
#include "SecurityOrigin.h"
37
#include "SecurityOrigin.h"
38
#include <bytecode/CodeBlock.h>
38
#include <inspector/ScriptCallStack.h>
39
#include <inspector/ScriptCallStack.h>
39
#include <inspector/ScriptCallStackFactory.h>
40
#include <inspector/ScriptCallStackFactory.h>
40
#include <interpreter/Interpreter.h>
41
#include <interpreter/Interpreter.h>
Lines 557-562 uint64_t toUInt64(ExecState* exec, JSValue value, IntegerConversionConfiguration a/Source/WebCore/bindings/js/JSDOMBinding.cpp_sec2
557
    return n;
558
    return n;
558
}
559
}
559
560
561
class GetCallerCodeBlockFunctor {
562
public:
563
    GetCallerCodeBlockFunctor() = default;
564
565
    StackVisitor::Status operator()(StackVisitor& visitor)
566
    {
567
        if (!m_hasSkippedFirstFrame) {
568
            m_hasSkippedFirstFrame = true;
569
            return StackVisitor::Continue;
570
        }
571
572
        m_codeBlock = visitor->codeBlock();
573
        return StackVisitor::Done;
574
    }
575
576
    CodeBlock* codeBlock() const { return m_codeBlock; }
577
578
private:
579
    bool m_hasSkippedFirstFrame { false };
580
    CodeBlock* m_codeBlock { nullptr };
581
};
582
583
DOMWindow* callerDOMWindow(ExecState* exec)
584
{
585
    GetCallerCodeBlockFunctor iter;
586
    exec->iterate(iter);
587
    CodeBlock* codeBlock = iter.codeBlock();
588
    return codeBlock ? &asJSDOMWindow(codeBlock->globalObject())->wrapped() : nullptr;
589
}
590
560
DOMWindow& activeDOMWindow(ExecState* exec)
591
DOMWindow& activeDOMWindow(ExecState* exec)
561
{
592
{
562
    return asJSDOMWindow(exec->lexicalGlobalObject())->wrapped();
593
    return asJSDOMWindow(exec->lexicalGlobalObject())->wrapped();
- a/Source/WebCore/bindings/js/JSDOMBinding.h +1 lines
Lines 78-83 struct ExceptionDetails { a/Source/WebCore/bindings/js/JSDOMBinding.h_sec1
78
78
79
typedef int ExceptionCode;
79
typedef int ExceptionCode;
80
80
81
DOMWindow* callerDOMWindow(JSC::ExecState*);
81
DOMWindow& activeDOMWindow(JSC::ExecState*);
82
DOMWindow& activeDOMWindow(JSC::ExecState*);
82
DOMWindow& firstDOMWindow(JSC::ExecState*);
83
DOMWindow& firstDOMWindow(JSC::ExecState*);
83
84
- a/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp -25 / +7 lines
Lines 252-281 bool JSDOMWindow::getOwnPropertySlot(JSObject* object, ExecState* exec, Property a/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp_sec1
252
    // (Particularly, is it correct that this exists here but not in getOwnPropertySlotByIndex?)
252
    // (Particularly, is it correct that this exists here but not in getOwnPropertySlotByIndex?)
253
    slot.setWatchpointSet(thisObject->m_windowCloseWatchpoints);
253
    slot.setWatchpointSet(thisObject->m_windowCloseWatchpoints);
254
254
255
    // FIXME: These are all bogus. Keeping these here make some tests pass that check these properties
256
    // are own properties of the window, but introduces other problems instead (e.g. if you overwrite
257
    // & delete then the original value is restored!) Should be removed.
258
    if (propertyName == exec->propertyNames().blur) {
259
        if (!Base::getOwnPropertySlot(thisObject, exec, propertyName, slot))
260
            slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, nonCachingStaticFunctionGetter<jsDOMWindowInstanceFunctionBlur, 0>);
261
        return true;
262
    }
263
    if (propertyName == exec->propertyNames().close) {
264
        if (!Base::getOwnPropertySlot(thisObject, exec, propertyName, slot))
265
            slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, nonCachingStaticFunctionGetter<jsDOMWindowInstanceFunctionClose, 0>);
266
        return true;
267
    }
268
    if (propertyName == exec->propertyNames().focus) {
269
        if (!Base::getOwnPropertySlot(thisObject, exec, propertyName, slot))
270
            slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, nonCachingStaticFunctionGetter<jsDOMWindowInstanceFunctionFocus, 0>);
271
        return true;
272
    }
273
    if (propertyName == exec->propertyNames().postMessage) {
274
        if (!Base::getOwnPropertySlot(thisObject, exec, propertyName, slot))
275
            slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, nonCachingStaticFunctionGetter<jsDOMWindowInstanceFunctionPostMessage, 2>);
276
        return true;
277
    }
278
279
    if (propertyName == exec->propertyNames().showModalDialog) {
255
    if (propertyName == exec->propertyNames().showModalDialog) {
280
        if (Base::getOwnPropertySlot(thisObject, exec, propertyName, slot))
256
        if (Base::getOwnPropertySlot(thisObject, exec, propertyName, slot))
281
            return true;
257
            return true;
Lines 612-619 static JSValue handlePostMessage(DOMWindow& impl, ExecState& state) a/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp_sec2
612
    if (state.hadException())
588
    if (state.hadException())
613
        return jsUndefined();
589
        return jsUndefined();
614
590
591
    DOMWindow* callerWindow = callerDOMWindow(&state);
592
    if (!callerWindow) {
593
        setDOMException(&state, TypeError);
594
        return jsUndefined();
595
    }
596
615
    ExceptionCode ec = 0;
597
    ExceptionCode ec = 0;
616
    impl.postMessage(message.release(), &messagePorts, targetOrigin, activeDOMWindow(&state), ec);
598
    impl.postMessage(message.release(), &messagePorts, targetOrigin, *callerWindow, ec);
617
    setDOMException(&state, ec);
599
    setDOMException(&state, ec);
618
600
619
    return jsUndefined();
601
    return jsUndefined();
- a/LayoutTests/ChangeLog +24 lines
Lines 1-3 a/LayoutTests/ChangeLog_sec1
1
2016-04-04  Chris Dumez  <cdumez@apple.com>
2
3
        MessageEvent.source window is incorrect once window has been reified
4
        https://bugs.webkit.org/show_bug.cgi?id=156227
5
        <rdar://problem/25545831>
6
7
        Reviewed by NOBODY (OOPS!).
8
9
        Add tests that cover using MessageEvent.source Window for messaging
10
        using postMessage(). There are 2 versions of the test, one where the
11
        main window is reified and one where it is not. The test that has a
12
        reified main window was failing because this fix.
13
14
        * fast/dom/Window/delete-operations-expected.txt: Added.
15
        * fast/dom/Window/delete-operations.html: Added.
16
        Make sure that operations on Window are indeed deletable. Previously,
17
        it would be impossible to delete postMessage, blur, focus and close.
18
19
        * fast/dom/Window/messageevent-source-postmessage-expected.txt: Added.
20
        * fast/dom/Window/messageevent-source-postmessage-reified-expected.txt: Added.
21
        * fast/dom/Window/messageevent-source-postmessage-reified.html: Added.
22
        * fast/dom/Window/messageevent-source-postmessage.html: Added.
23
        * fast/dom/Window/resources/messageevent-source-postmessage-frame.html: Added.
24
1
2016-04-04  Ryan Haddad  <ryanhaddad@apple.com>
25
2016-04-04  Ryan Haddad  <ryanhaddad@apple.com>
2
26
3
        Marking plugins/focus.html as flaky on mac
27
        Marking plugins/focus.html as flaky on mac
- a/LayoutTests/fast/dom/Window/delete-operations-expected.txt +75 lines
Line 0 a/LayoutTests/fast/dom/Window/delete-operations-expected.txt_sec1
1
Tests deleting window operations works as expected
2
3
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
4
5
6
PASS window.postMessage is an instance of Function
7
window.postMessage = 1
8
PASS window.postMessage is 1
9
PASS delete window.postMessage is true
10
PASS window.postMessage is undefined.
11
12
PASS window.focus is an instance of Function
13
window.focus = 1
14
PASS window.focus is 1
15
PASS delete window.focus is true
16
PASS window.focus is undefined.
17
18
PASS window.blur is an instance of Function
19
window.blur = 1
20
PASS window.blur is 1
21
PASS delete window.blur is true
22
PASS window.blur is undefined.
23
24
PASS window.close is an instance of Function
25
window.close = 1
26
PASS window.close is 1
27
PASS delete window.close is true
28
PASS window.close is undefined.
29
30
PASS window.open is an instance of Function
31
window.open = 1
32
PASS window.open is 1
33
PASS delete window.open is true
34
PASS window.open is undefined.
35
36
PASS window.showModalDialog is an instance of Function
37
window.showModalDialog = 1
38
PASS window.showModalDialog is 1
39
PASS delete window.showModalDialog is true
40
PASS window.showModalDialog is undefined.
41
42
PASS window.alert is an instance of Function
43
window.alert = 1
44
PASS window.alert is 1
45
PASS delete window.alert is true
46
PASS window.alert is undefined.
47
48
PASS window.confirm is an instance of Function
49
window.confirm = 1
50
PASS window.confirm is 1
51
PASS delete window.confirm is true
52
PASS window.confirm is undefined.
53
54
PASS window.prompt is an instance of Function
55
window.prompt = 1
56
PASS window.prompt is 1
57
PASS delete window.prompt is true
58
PASS window.prompt is undefined.
59
60
PASS window.stop is an instance of Function
61
window.stop = 1
62
PASS window.stop is 1
63
PASS delete window.stop is true
64
PASS window.stop is undefined.
65
66
PASS window.scroll is an instance of Function
67
window.scroll = 1
68
PASS window.scroll is 1
69
PASS delete window.scroll is true
70
PASS window.scroll is undefined.
71
72
PASS successfullyParsed is true
73
74
TEST COMPLETE
75
- a/LayoutTests/fast/dom/Window/delete-operations.html +31 lines
Line 0 a/LayoutTests/fast/dom/Window/delete-operations.html_sec1
1
<!DOCTYPE html>
2
<body>
3
<script src="../../../resources/js-test-pre.js"></script>
4
<script>
5
description("Tests deleting window operations works as expected");
6
7
function testFunction(functionName)
8
{
9
    shouldBeType("window." + functionName, "Function");
10
    evalAndLog("window." + functionName + " = 1");
11
    shouldBe("window." + functionName, "1");
12
    shouldBeTrue("delete window." + functionName);
13
    shouldBeUndefined("window." + functionName);
14
    debug("");
15
}
16
17
testFunction("postMessage");
18
testFunction("focus");
19
testFunction("blur");
20
testFunction("close");
21
testFunction("open");
22
testFunction("showModalDialog");
23
testFunction("alert");
24
testFunction("confirm");
25
testFunction("prompt");
26
testFunction("stop");
27
testFunction("scroll");
28
29
</script>
30
<script src="../../../resources/js-test-post.js"></script>
31
</body>
- a/LayoutTests/fast/dom/Window/messageevent-source-postmessage-expected.txt +35 lines
Line 0 a/LayoutTests/fast/dom/Window/messageevent-source-postmessage-expected.txt_sec1
1
Tests that MessageEvent.source is correct and can be used for messaging.
2
3
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
4
5
6
* Sending message 1 to child
7
* Parent received message 2 from child
8
PASS messageEvent.source is frames[0]
9
PASS messageEvent.data is counter + 1
10
* Sending message 3 to child
11
* Parent received message 4 from child
12
PASS messageEvent.source is frames[0]
13
PASS messageEvent.data is counter + 1
14
* Sending message 5 to child
15
* Parent received message 6 from child
16
PASS messageEvent.source is frames[0]
17
PASS messageEvent.data is counter + 1
18
PASS successfullyParsed is true
19
20
TEST COMPLETE
21
22
23
--------
24
Frame: '<!--framePath //<!--frame0-->-->'
25
--------
26
* Child received message 1 from parent
27
PASS messageEvent.source is parent
28
* Sending message 2 to parent
29
* Child received message 3 from parent
30
PASS messageEvent.source is parent
31
* Sending message 4 to parent
32
* Child received message 5 from parent
33
PASS messageEvent.source is parent
34
* Sending message 6 to parent
35
- a/LayoutTests/fast/dom/Window/messageevent-source-postmessage-reified-expected.txt +35 lines
Line 0 a/LayoutTests/fast/dom/Window/messageevent-source-postmessage-reified-expected.txt_sec1
1
Tests that MessageEvent.source is correct and can be used for messaging (reified Window case).
2
3
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
4
5
6
* Sending message 1 to child
7
* Parent received message 2 from child
8
PASS messageEvent.source is frames[0]
9
PASS messageEvent.data is counter + 1
10
* Sending message 3 to child
11
* Parent received message 4 from child
12
PASS messageEvent.source is frames[0]
13
PASS messageEvent.data is counter + 1
14
* Sending message 5 to child
15
* Parent received message 6 from child
16
PASS messageEvent.source is frames[0]
17
PASS messageEvent.data is counter + 1
18
PASS successfullyParsed is true
19
20
TEST COMPLETE
21
22
23
--------
24
Frame: '<!--framePath //<!--frame0-->-->'
25
--------
26
* Child received message 1 from parent
27
PASS messageEvent.source is parent
28
* Sending message 2 to parent
29
* Child received message 3 from parent
30
PASS messageEvent.source is parent
31
* Sending message 4 to parent
32
* Child received message 5 from parent
33
PASS messageEvent.source is parent
34
* Sending message 6 to parent
35
- a/LayoutTests/fast/dom/Window/messageevent-source-postmessage-reified.html +42 lines
Line 0 a/LayoutTests/fast/dom/Window/messageevent-source-postmessage-reified.html_sec1
1
<!DOCTYPE html>
2
<html>
3
<script src="../../../resources/js-test-pre.js"></script>
4
<body onload="runTest()">
5
<script>
6
description("Tests that MessageEvent.source is correct and can be used for messaging (reified Window case).");
7
jsTestIsAsync = true;
8
9
// Reify the window.
10
window.test = 1;
11
delete window.test;
12
13
if (window.testRunner)
14
    testRunner.dumpChildFramesAsText();
15
16
counter = 1;
17
18
window.onmessage = function(e) {
19
    debug("* Parent received message " + e.data + " from child");
20
    messageEvent = e;
21
    shouldBe("messageEvent.source", "frames[0]");
22
    shouldBe("messageEvent.data", "counter + 1");
23
    if (messageEvent.data > 5) {
24
        finishJSTest();
25
        return;
26
    }
27
    counter = messageEvent.data + 1;
28
    debug("* Sending message " + counter + " to child");
29
    messageEvent.source.postMessage(counter, "*");
30
}
31
32
function runTest()
33
{
34
    debug("* Sending message " + counter + " to child");
35
    frames[0].postMessage(counter, "*");
36
}
37
38
</script>
39
<iframe src="resources/messageevent-source-postmessage-frame.html"></iframe>
40
<script src="../../../resources/js-test-post.js"></script>
41
</body>
42
</html>
- a/LayoutTests/fast/dom/Window/messageevent-source-postmessage.html +38 lines
Line 0 a/LayoutTests/fast/dom/Window/messageevent-source-postmessage.html_sec1
1
<!DOCTYPE html>
2
<html>
3
<script src="../../../resources/js-test-pre.js"></script>
4
<body onload="runTest()">
5
<script>
6
description("Tests that MessageEvent.source is correct and can be used for messaging.");
7
jsTestIsAsync = true;
8
9
if (window.testRunner)
10
    testRunner.dumpChildFramesAsText();
11
12
counter = 1;
13
14
window.onmessage = function(e) {
15
    debug("* Parent received message " + e.data + " from child");
16
    messageEvent = e;
17
    shouldBe("messageEvent.source", "frames[0]");
18
    shouldBe("messageEvent.data", "counter + 1");
19
    if (messageEvent.data > 5) {
20
        finishJSTest();
21
        return;
22
    }
23
    counter = messageEvent.data + 1;
24
    debug("* Sending message " + counter + " to child");
25
    messageEvent.source.postMessage(counter, "*");
26
}
27
28
function runTest()
29
{
30
    debug("* Sending message " + counter + " to child");
31
    frames[0].postMessage(counter, "*");
32
}
33
34
</script>
35
<iframe src="resources/messageevent-source-postmessage-frame.html"></iframe>
36
<script src="../../../resources/js-test-post.js"></script>
37
</body>
38
</html>
- a/LayoutTests/fast/dom/Window/resources/messageevent-source-postmessage-frame.html +16 lines
Line 0 a/LayoutTests/fast/dom/Window/resources/messageevent-source-postmessage-frame.html_sec1
1
<!DOCTYPE html>
2
<body>
3
<script src="../../../../resources/js-test-pre.js"></script>
4
<script>
5
jsTestIsAsync = true;
6
7
window.onmessage = function(e) {
8
    debug("* Child received message " + e.data + " from parent");
9
    messageEvent = e;
10
    shouldBe("messageEvent.source", "parent");
11
    debug("* Sending message " + (e.data + 1) + " to parent");
12
    messageEvent.source.postMessage(e.data + 1, "*");
13
}
14
</script>
15
<script src="../../../../resources/js-test-post.js"></script>
16
</body>

Return to Bug 156227