|
1 <?xml version="1.0"?> |
|
2 <?xml-stylesheet type="text/css" href="chrome://global/skin"?> |
|
3 <?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> |
|
4 <!-- |
|
5 https://bugzilla.mozilla.org/show_bug.cgi?id=937317 |
|
6 --> |
|
7 <window title="Mozilla Bug 937317" |
|
8 xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> |
|
9 <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> |
|
10 |
|
11 <!-- test results are displayed in the html:body --> |
|
12 <body xmlns="http://www.w3.org/1999/xhtml"> |
|
13 <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=937317" |
|
14 target="_blank">Mozilla Bug 937317</a> |
|
15 </body> |
|
16 |
|
17 <!-- test code goes here --> |
|
18 <iframe src="data:text/html,"></iframe> |
|
19 <script type="application/javascript"> |
|
20 <![CDATA[ |
|
21 |
|
22 /** Test for the script settings stack. **/ |
|
23 SimpleTest.waitForExplicitFinish(); |
|
24 addLoadEvent(function() { |
|
25 const Cu = Components.utils; |
|
26 Cu.import("resource://gre/modules/Promise.jsm"); |
|
27 iwin = window[0]; |
|
28 |
|
29 // Smoketest. |
|
30 is(Cu.getIncumbentGlobal(), window, "smoketest"); |
|
31 |
|
32 // Calling a cross-compartment non-scripted function changes the |
|
33 // compartment, but not the incumbent script settings object. |
|
34 var sb = new Cu.Sandbox(window, { wantComponents: true }); |
|
35 is(sb.Components.utils.getIncumbentGlobal(), window, "cross-compartment sb non-scripted"); |
|
36 is(iwin.Components.utils.getIncumbentGlobal(), window, "cross-compartment win non-scripted"); |
|
37 |
|
38 // If we call a scripted function in the other compartment, that becomes |
|
39 // the incumbent script. |
|
40 function gib() { return Components.utils.getIncumbentGlobal(); }; |
|
41 Cu.evalInSandbox(gib.toSource(), sb); |
|
42 iwin.eval(gib.toSource()); |
|
43 is(sb.gib(), sb, "cross-compartment sb scripted"); |
|
44 is(iwin.gib(), iwin, "cross-compartment win scripted"); |
|
45 |
|
46 // Eval-ing top-level script in another component makes that compartment the |
|
47 // incumbent script. |
|
48 is(Cu.evalInSandbox('Components.utils.getIncumbentGlobal()', sb), sb, 'eval sb'); |
|
49 is(iwin.eval('Components.utils.getIncumbentGlobal()'), iwin, 'eval iwin'); |
|
50 |
|
51 // Make sure that the callback mechanism works. |
|
52 function makeCallback(expectedGlobal, deferred, kind) { |
|
53 function cb(incumbentGlobal) { |
|
54 is(incumbentGlobal, expectedGlobal, "Callback got the right incumbent global: " + kind); |
|
55 if (deferred) |
|
56 deferred.resolve(); |
|
57 } |
|
58 info("Generated callback: " + kind); |
|
59 return cb; |
|
60 } |
|
61 |
|
62 var bound = Cu.getIncumbentGlobal.bind(Cu, makeCallback(window, undefined, "simple bound")); |
|
63 is(bound(), window, "Bound method returns the right global"); |
|
64 |
|
65 // Callbacks grab the incumbent script at the time of invocation. |
|
66 // |
|
67 // Note - We avoid calling the initial defer |d| so that it's not in-scope for everything below. |
|
68 let initialDefer = Promise.defer(); |
|
69 setTimeout(Cu.getIncumbentGlobal.bind(Cu, makeCallback(window, initialDefer, "same-global setTimeout")), 0); |
|
70 initialDefer.promise.then(function() { |
|
71 |
|
72 // Try cross-global setTimeout where |window| is the incumbent script when the callback is created. |
|
73 let d = Promise.defer(); |
|
74 iwin.setTimeout(Cu.getIncumbentGlobal.bind(Cu, makeCallback(window, d, "cross-global setTimeout by |window|")), 0); |
|
75 return d.promise; |
|
76 }).then(function() { |
|
77 |
|
78 // Try cross-global setTimeout where |iwin| is the incumbent script when the callback is created. |
|
79 let d = Promise.defer(); |
|
80 iwin.wrappedJSObject.timeoutFun = Cu.getIncumbentGlobal.bind(Cu, makeCallback(iwin, d, "cross-global setTimeout by |iwin|")); |
|
81 iwin.eval('setTimeout(timeoutFun, 0);'); |
|
82 return d.promise; |
|
83 }).then(function() { |
|
84 |
|
85 // The incumbent script override doesn't take effect if the callback is scripted. |
|
86 let d = Promise.defer(); |
|
87 iwin.wrappedJSObject.timeoutFun2 = Cu.getIncumbentGlobal.bind(Cu, makeCallback(iwin, d, "cross-global setTimeout of scripted function")); |
|
88 iwin.eval('let timeoutFun2Wrapper = function() { timeoutFun2(); }'); |
|
89 setTimeout(iwin.wrappedJSObject.timeoutFun2Wrapper, 0); |
|
90 return d.promise; |
|
91 }).then(function() { |
|
92 |
|
93 // Try event listeners. |
|
94 let d = Promise.defer(); |
|
95 let body = iwin.document.body; |
|
96 body.addEventListener('click', Cu.getIncumbentGlobal.bind(Cu, makeCallback(window, d, "cross-global event listener"))); |
|
97 body.dispatchEvent(new iwin.MouseEvent('click')); |
|
98 return d.promise; |
|
99 |
|
100 }).then(function() { |
|
101 |
|
102 // Try an event handler set by |iwin|. |
|
103 let d = Promise.defer(); |
|
104 let body = iwin.document.body; |
|
105 iwin.wrappedJSObject.handler = Cu.getIncumbentGlobal.bind(Cu, makeCallback(iwin, d, "cross-global event handler")); |
|
106 iwin.eval('document.body.onmousemove = handler'); |
|
107 body.dispatchEvent(new iwin.MouseEvent('mousemove')); |
|
108 return d.promise; |
|
109 |
|
110 }).then(function() { |
|
111 |
|
112 // Try an event handler compiled by a content attribute. |
|
113 let d = Promise.defer(); |
|
114 let body = iwin.document.body; |
|
115 iwin.wrappedJSObject.innerHandler = Cu.getIncumbentGlobal.bind(Cu, makeCallback(iwin, d, "cross-global compiled event handler")); |
|
116 iwin.eval("document.body.setAttribute('onmouseout', 'innerHandler()')"); |
|
117 body.dispatchEvent(new iwin.MouseEvent('mouseout')); |
|
118 return d.promise; |
|
119 }).then(function() { |
|
120 |
|
121 SimpleTest.finish(); |
|
122 }); |
|
123 }); |
|
124 |
|
125 ]]> |
|
126 </script> |
|
127 </window> |