2 <?xml-stylesheet href=
"chrome://global/skin" type=
"text/css"?>
3 <?xml-stylesheet href=
"chrome://mochikit/content/tests/SimpleTest/test.css"
6 https://bugzilla.mozilla.org/show_bug.cgi?id=500931
8 <window title=
"Mozilla Bug 522764"
9 xmlns=
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
10 <script src=
"chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
12 <!-- test results are displayed in the html:body -->
13 <body xmlns=
"http://www.w3.org/1999/xhtml">
14 <a href=
"https://bugzilla.mozilla.org/show_bug.cgi?id=522764 "
15 target=
"_blank">Mozilla Bug
522764 </a>
18 <!-- test code goes here -->
19 <script type=
"application/javascript"><![CDATA[
20 add_task(async () =
> {
21 var sandbox = new Cu.Sandbox(
"about:blank");
23 await SpecialPowers.pushPrefEnv({
"set": [[
"security.allow_eval_with_system_principal",
26 /* eslint-disable no-eval */
29 if (typeof x != 'object' && typeof x != 'function')
33 if (typeof x ==
"function")
34 rval = eval(`(${x.toString()})`);
36 if (x.__lookupGetter__(i))
37 rval.__defineGetter__(i, eval(`(${x.__lookupGetter__(i).toString()})`))
39 rval[i] = getCOW(x[i]);
44 // Give the sandbox a way to create ChromeObjectWrapped objects.
45 sandbox.getCOW = getCOW;
47 // Define test API functions in the sandbox.
48 const TEST_API = ['is', 'isnot', 'ok', 'todo_is', 'todo_isnot', 'todo'];
49 TEST_API.forEach(function(name) { sandbox[name] = window[name]; });
51 sandbox.chromeGet = function (obj, prop) { return obj[prop]; };
54 function getNames(cow) {
56 for (let name in cow) {
62 // This function is actually stringified and run inside a
63 // sandbox with content privileges.
65 // TODO: This could use some refactoring; creating helper
66 // functions like assertIsWritable(myObj, 'someproperty') might
69 function isPropHidden(obj, propName, desc) {
71 is(obj[propName], undefined,
72 "getting " + propName +
" on " + desc +
" should return undefined");
73 ok(!(propName in obj),
74 propName +
" on " + desc +
" should act as if it doesn't exist");
75 ok(!Object.hasOwnProperty.call(obj, propName),
76 propName +
" on " + desc +
" should act as if it doesn't exist");
78 ok(false,
"getting " + propName +
" on " + desc +
" threw " + e);
82 const PROPS_TO_TEST = ['foo', 'bar', 'prototype'];
85 var nonempty = {foo:
42, bar:
33};
86 is(getCOW(empty).foo, undefined,
87 "shouldn't throw when accessing exposed properties that don't exist");
89 PROPS_TO_TEST.forEach(function(name) {
90 isPropHidden(getCOW(nonempty), name,
"object without exposedProps");
93 // Test function objects.
94 var func = function() { return
42; };
95 func.foo =
"foo property";
96 var funcCOW = getCOW(func);
99 ok(false, 'Functions are no longer COWable');
101 ok(/denied|insecure/.test(e), 'Functions are no longer COWable');
103 is(funcCOW(),
42,
"Chrome functions should be callable");
105 // Test writable property
106 var writable = getCOW({});
108 ok(!(
"foo" in writable),
109 "non-existing write-only property shouldn't exist");
111 ok(false,
"writing to a write-only exposed prop should throw");
113 ok(/Permission denied/.test(e),
114 "writing to a write-only exposed prop should throw the right error");
116 is(writable.foo, undefined,
117 "reading from a write-only exposed prop should return undefined");
120 ok(false,
"deleting a write-only exposed prop should throw");
122 ok(true,
"deleting a write-only exposed prop should throw " + e);
125 // Test readable property
126 var readable = { foo:
5,
129 isPropHidden(getCOW(readable),
"foo", undefined,
130 "reading from a readable exposed prop shouldn't work");
132 ok(false,
"reading from a readable exposed prop shouldn't throw " + e);
135 getCOW(readable).foo =
1;
136 ok(false,
"writing to a read-only exposed prop should fail");
138 ok(/Permission denied/.test(e),
139 "writing to a read-only exposed prop should fail");
142 delete getCOW(readable).foo;
143 ok(false,
"deleting a read-only exposed prop shouldn't work");
145 ok(/Permission denied/.test(e),
146 "deleting a read-only exposed prop should throw error");
150 var props = getNames(getCOW(readable));
151 is(props.length,
0,
"COW w/ one exposed prop should not enumerate");
153 ok(false,
"COW w/ a readable prop should not raise exc " +
154 "on enumeration: " + e);
157 // Test read/write property
158 var readwrite = getCOW({});
160 ok(!(
"foo" in readwrite),
161 "non-existing readwrite property shouldn't exist");
163 ok(false,
"writing to a readwrite exposed prop should throw");
165 ok(/Permission denied/.test(e),
166 "writing to a readwrite exposed prop should throw the right error");
169 delete readwrite.foo;
170 ok(false,
"deleting a readwrite prop should throw");
172 ok(/Permission denied/.test(e),
173 "deleting a readwrite exposed prop should throw the right error");
176 // Readables and functions
178 var COWFunc = getCOW((function() { return
5; }));
179 is(COWFunc(),
5,
"COWed functions should be callable");
181 todo(false,
"COWed functions should not raise " + e);
185 // Stringify the COW test suite and directly evaluate it in the sandbox.
186 Cu.evalInSandbox('(' + COWTests.toString() + ')()', sandbox);
188 // Test that COWed objects passing from content to chrome get unwrapped.
189 function returnCOW() {
190 return getCOW({bar:
6});
193 var unwrapped = Cu.evalInSandbox(
194 '(' + returnCOW.toString() + ')()',
200 "COWs should be unwrapped when entering chrome space");
202 todo(false,
"COWs should be unwrapped when entering chrome space, " +