Bug 718543 - Preserve SpecialPowers wrapper identity with a WeakMap cache. r=mrbkap

This commit is contained in:
Bobby Holley 2012-02-19 15:47:12 -08:00
parent 3e6a76d272
commit 80cafe8e18
2 changed files with 23 additions and 6 deletions

View File

@ -156,6 +156,9 @@ function doApply(fun, invocant, args) {
return Function.prototype.apply.call(fun, invocant, args);
}
// Use a weak map to cache wrappers. This allows the wrappers to preserve identity.
var wrapperCache = WeakMap();
function wrapPrivileged(obj) {
// Primitives pass straight through.
@ -166,10 +169,15 @@ function wrapPrivileged(obj) {
if (isWrapper(obj))
throw "Trying to double-wrap object!";
// Try the cache.
if (wrapperCache.has(obj))
return wrapperCache.get(obj);
// Make our core wrapper object.
var handler = new SpecialPowersHandler(obj);
// If the object is callable, make a function proxy.
var wrapper;
if (typeof obj === "function") {
var callTrap = function() {
// The invocant and arguments may or may not be wrappers. Unwrap them if necessary.
@ -193,11 +201,16 @@ function wrapPrivileged(obj) {
return wrapPrivileged(new FakeConstructor());
};
return Proxy.createFunction(handler, callTrap, constructTrap);
wrapper = Proxy.createFunction(handler, callTrap, constructTrap);
}
// Otherwise, just make a regular object proxy.
else {
wrapper = Proxy.create(handler);
}
// Otherwise, just make a regular object proxy.
return Proxy.create(handler);
// Cache the wrapper and return it.
wrapperCache.set(obj, wrapper);
return wrapper;
};
function unwrapPrivileged(x) {
@ -408,9 +421,6 @@ SpecialPowersAPI.prototype = {
*
* Known Issues:
*
* - The wrapping function does not preserve identity, so
* SpecialPowers.wrap(foo) !== SpecialPowers.wrap(foo). See bug 718543.
*
* - The wrapper cannot see expando properties on unprivileged DOM objects.
* That is to say, the wrapper uses Xray delegation.
*

View File

@ -134,6 +134,13 @@ function starttest(){
noxray.b = 122;
is(noxray_wrapper.b, 122, "Should be able to shadow.");
// Check that the wrapper preserves identity.
var someIdentityObject = {a: 2};
ok(SpecialPowers.wrap(someIdentityObject) === SpecialPowers.wrap(someIdentityObject),
"SpecialPowers wrapping should preserve identity!");
ok(webnav === SpecialPowers.wrap(SpecialPowers.unwrap(webnav)),
"SpecialPowers wrapping should preserve identity!");
info("\nProfile::SpecialPowersRunTime: " + (new Date() - startTime) + "\n");
SimpleTest.finish();
}