Bug 1186213 - Add an API to deep-freeze the result of Cu.cloneInto. r=gkrizsanits

This commit is contained in:
Bobby Holley 2015-07-21 14:57:00 +02:00
parent 06c3dd1246
commit 4dac367856
4 changed files with 51 additions and 2 deletions

View File

@ -271,7 +271,17 @@ StackScopedClone(JSContext* cx, StackScopedCloneOptions& options,
}
// Now recreate the clones in the target compartment.
return buffer.read(cx, val, &gStackScopedCloneCallbacks, &data);
if (!buffer.read(cx, val, &gStackScopedCloneCallbacks, &data))
return false;
// Deep-freeze if requested.
if (options.deepFreeze && val.isObject()) {
RootedObject obj(cx, &val.toObject());
if (!JS_DeepFreezeObject(cx, obj))
return false;
}
return true;
}
// Note - This function mirrors the logic of CheckPassToChrome in

View File

@ -3567,11 +3567,13 @@ public:
: OptionsBase(cx, options)
, wrapReflectors(false)
, cloneFunctions(false)
, deepFreeze(false)
{ }
virtual bool Parse() {
return ParseBoolean("wrapReflectors", &wrapReflectors) &&
ParseBoolean("cloneFunctions", &cloneFunctions);
ParseBoolean("cloneFunctions", &cloneFunctions) &&
ParseBoolean("deepFreeze", &deepFreeze);
}
// When a reflector is encountered, wrap it rather than aborting the clone.
@ -3580,6 +3582,9 @@ public:
// When a function is encountered, clone it (exportFunction-style) rather than
// aborting the clone.
bool cloneFunctions;
// If true, the resulting object is deep-frozen after being cloned.
bool deepFreeze;
};
JSObject*

View File

@ -0,0 +1,33 @@
const Cu = Components.utils;
function checkThrows(f, rgxp) { try { f(); do_check_false(); } catch (e) { do_check_true(rgxp.test(e)); } }
var o = { foo: 42, bar : { tick: 'tock' } };
function checkClone(clone, frozen) {
var waived = Cu.waiveXrays(clone);
function touchFoo() { "use strict"; waived.foo = 12; do_check_eq(waived.foo, 12); }
function touchBar() { "use strict"; waived.bar.tick = 'tack'; do_check_eq(waived.bar.tick, 'tack'); }
function addProp() { "use strict"; waived.newProp = 100; do_check_eq(waived.newProp, 100); }
if (!frozen) {
touchFoo();
touchBar();
addProp();
} else {
checkThrows(touchFoo, /read-only/);
checkThrows(touchBar, /read-only/);
checkThrows(addProp, /extensible/);
}
var desc = Object.getOwnPropertyDescriptor(waived, 'foo');
do_check_eq(desc.writable, !frozen);
do_check_eq(desc.configurable, !frozen);
desc = Object.getOwnPropertyDescriptor(waived.bar, 'tick');
do_check_eq(desc.writable, !frozen);
do_check_eq(desc.configurable, !frozen);
}
function run_test() {
var sb = new Cu.Sandbox(null);
checkClone(Cu.waiveXrays(Cu.cloneInto(o, sb)), false);
checkClone(Cu.cloneInto(o, sb, { deepFreeze: true }), true);
}

View File

@ -62,6 +62,7 @@ support-files =
[test_bug1170311.js]
[test_bug_442086.js]
[test_callFunctionWithAsyncStack.js]
[test_deepFreezeClone.js]
[test_file.js]
[test_blob.js]
[test_blob2.js]