|
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=933681 |
|
6 --> |
|
7 <window title="Mozilla Bug 933681" |
|
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=933681" |
|
14 target="_blank">Mozilla Bug 933681</a> |
|
15 </body> |
|
16 |
|
17 <!-- test code goes here --> |
|
18 <script type="application/javascript"> |
|
19 <![CDATA[ |
|
20 |
|
21 /** Test for ES constructors on Xrayed globals. **/ |
|
22 SimpleTest.waitForExplicitFinish(); |
|
23 const Cu = Components.utils; |
|
24 let global = Cu.getGlobalForObject.bind(Cu); |
|
25 |
|
26 simpleConstructors = ['Object', 'Function', 'Array', 'Boolean', 'Date', 'Number', |
|
27 'String', 'RegExp', 'Error', 'InternalError', 'EvalError', |
|
28 'RangeError', 'ReferenceError', 'SyntaxError', 'TypeError', |
|
29 'URIError', 'ArrayBuffer', 'Int8Array', 'Uint8Array', |
|
30 'Int16Array', 'Uint16Array', 'Int32Array', 'Uint32Array', |
|
31 'Float32Array', 'Float64Array', 'Uint8ClampedArray', |
|
32 'WeakMap', 'Map', 'Set']; |
|
33 |
|
34 function go() { |
|
35 window.iwin = document.getElementById('ifr').contentWindow; |
|
36 |
|
37 // Test constructors that can be instantiated with zero arguments. |
|
38 for (var c of simpleConstructors) { |
|
39 ok(iwin[c], "Constructors appear: " + c); |
|
40 is(iwin[c], Cu.unwaiveXrays(iwin.wrappedJSObject[c]), |
|
41 "we end up with the appropriate constructor: " + c); |
|
42 is(Cu.unwaiveXrays(Cu.waiveXrays(new iwin[c]).constructor), iwin[c], |
|
43 "constructor property is set up right: " + c); |
|
44 is(Object.getPrototypeOf(new iwin[c]), |
|
45 Cu.unwaiveXrays(Cu.waiveXrays(iwin[c]).prototype), |
|
46 "prototype is correct: " + c); |
|
47 is(global(new iwin[c]), iwin, "Got the right global: " + c); |
|
48 } |
|
49 |
|
50 // Test Object in more detail. |
|
51 var num = new iwin.Object(4); |
|
52 is(num.valueOf(), 4, "primitive object construction works"); |
|
53 is(global(num), iwin, "correct global for num"); |
|
54 var obj = new iwin.Object(); |
|
55 obj.foo = 2; |
|
56 var withProto = iwin.Object.create(obj); |
|
57 is(global(withProto), iwin, "correct global for withProto"); |
|
58 is(withProto.foo, 2, "Inherits properly"); |
|
59 |
|
60 // Test Function. |
|
61 var primitiveFun = new iwin.Function('return 2'); |
|
62 is(global(primitiveFun), iwin, "function construction works"); |
|
63 is(primitiveFun(), 2, "basic function works"); |
|
64 var doSetFoo = new iwin.Function('arg', 'arg.foo = 2;'); |
|
65 is(global(doSetFoo), iwin, "function with args works"); |
|
66 try { |
|
67 doSetFoo(new Object()); |
|
68 ok(false, "should have thrown while setting property on object"); |
|
69 } catch (e) { |
|
70 ok(!!/denied/.test(e), "Threw correctly: " + e); |
|
71 } |
|
72 var factoryFun = new iwin.Function('return {foo: 32}'); |
|
73 is(global(factoryFun), iwin, "proper global for factoryFun"); |
|
74 is(factoryFun().foo, 32, "factoryFun invokable"); |
|
75 is(global(factoryFun()), iwin, "minted objects live in the content scope"); |
|
76 |
|
77 // Test interface objects that don't actually construct things. |
|
78 is(iwin.Math.tan(4.5), Math.tan(4.5), "Math.tan works"); |
|
79 is(iwin.Math.E, Math.E, "Math.E works"); |
|
80 var json = JSON.stringify({a: 2, b: 'hi', c: {d: 'there'}}); |
|
81 is(global(iwin.JSON.parse(json)), iwin, "JSON rehydrated into the right context"); |
|
82 is(iwin.JSON.stringify(iwin.JSON.parse(json)), json, "JSON composition identity holds"); |
|
83 |
|
84 // Test proxies. |
|
85 var targetObject = new iwin.Object(); |
|
86 targetObject.foo = 9; |
|
87 var forwardingProxy = new iwin.Proxy(targetObject, new iwin.Object()); |
|
88 is(global(forwardingProxy), iwin, "proxy global correct"); |
|
89 is(forwardingProxy.foo, 9, "forwards correctly"); |
|
90 // NB: COW-implemented proxy handlers are super dangerous, and we should not |
|
91 // encourage them. |
|
92 var handler = {get: function(target, name) { return name * 2; }, __exposedProps__: {get: 'r'}}; |
|
93 var doublingProxy = new iwin.Proxy(targetObject, handler); |
|
94 is(global(doublingProxy), iwin, "doubling proxy global correct"); |
|
95 is(doublingProxy[3], 6, "Doubles correctly"); |
|
96 is(doublingProxy[20], 40, "Doubles correctly"); |
|
97 |
|
98 // Test eval. |
|
99 var toEval = "({a: 2, b: {foo: 'bar'}, f: function() { return window; }})"; |
|
100 is(global(iwin.eval(toEval)), iwin, "eval creates objects in the correct global"); |
|
101 is(iwin.eval(toEval).b.foo, 'bar', "eval-ed object looks right"); |
|
102 is(iwin.eval(toEval).f(), iwin, "evaled function works right"); |
|
103 |
|
104 testDate(); |
|
105 |
|
106 // We could also test DataView and Iterator here for completeness, but it's |
|
107 // more trouble than it's worth. |
|
108 |
|
109 |
|
110 SimpleTest.finish(); |
|
111 } |
|
112 |
|
113 function filterOut(array, props) { |
|
114 return array.filter(p => props.indexOf(p) == -1); |
|
115 } |
|
116 |
|
117 function testXray(classname, xray, xray2, propsToSkip) { |
|
118 propsToSkip = propsToSkip || []; |
|
119 let xrayProto = Object.getPrototypeOf(xray); |
|
120 let localProto = window[classname].prototype; |
|
121 let protoProps = filterOut(Object.getOwnPropertyNames(localProto), propsToSkip).sort(); |
|
122 let protoMethods = protoProps.filter(name => typeof localProto[name] == 'function' && |
|
123 name != 'constructor'); |
|
124 ok(protoMethods.length > 0, "Need something to test"); |
|
125 is(xrayProto, iwin[classname].prototype, "Xray proto is correct"); |
|
126 is(xrayProto, xray.__proto__, "Proto accessors agree"); |
|
127 is(Object.getPrototypeOf(xrayProto), iwin.Object.prototype, "proto proto is correct"); |
|
128 for (let name of protoMethods) { |
|
129 info("Running tests for property: " + name); |
|
130 ok(xrayProto.hasOwnProperty(name), "proto should have the property as own"); |
|
131 ok(!xray.hasOwnProperty(name), "instance should not have the property as own"); |
|
132 let method = xrayProto[name]; |
|
133 is(typeof method, 'function', "Methods from Xrays are functions"); |
|
134 is(global(method), window, "Methods from Xrays are local"); |
|
135 ok(method instanceof Function, "instanceof works on methods from Xrays"); |
|
136 is(xrayProto[name], method, "Holder caching works properly"); |
|
137 is(xray[name], method, "Proto props resolve on the instance"); |
|
138 let local = localProto[name]; |
|
139 is(method.length, local.length, "Function.length identical"); |
|
140 if (method.length == 0) { |
|
141 is(xray[name]() + "", local.call(xray) + "", |
|
142 "Xray and local method results stringify identically"); |
|
143 is(xray[name]() + "", xray.wrappedJSObject[name]() + "", |
|
144 "Xray and waived method results stringify identically"); |
|
145 } |
|
146 } |
|
147 is(Object.getOwnPropertyNames(xrayProto).sort().toSource(), |
|
148 protoProps.toSource(), "getOwnPropertyNames works"); |
|
149 |
|
150 is(xrayProto.constructor, iwin[classname], "constructor property works"); |
|
151 |
|
152 xrayProto.expando = 42; |
|
153 is(xray.expando, 42, "Xrayed instances see proto expandos"); |
|
154 is(xray2.expando, 42, "Xrayed instances see proto expandos"); |
|
155 } |
|
156 |
|
157 function testDate() { |
|
158 // toGMTString is handled oddly in the engine. We don't bother to support |
|
159 // it over Xrays. |
|
160 // |
|
161 // We don't yet support self-hosted functions on Xrays. See bug 972987. |
|
162 let propsToSkip = ['toGMTString', 'toLocaleString', |
|
163 'toLocaleDateString', 'toLocaleTimeString']; |
|
164 testXray('Date', new iwin.Date(), new iwin.Date(), propsToSkip); |
|
165 } |
|
166 |
|
167 ]]> |
|
168 </script> |
|
169 <iframe id="ifr" onload="go();" src="http://example.org/tests/js/xpconnect/tests/mochitest/file_empty.html" /> |
|
170 </window> |