author | Bobby Holley <bobbyholley@gmail.com> |
Sun, 19 Feb 2012 15:47:12 -0800 | |
changeset 87194 | f9145dab4be93acbc202f4c9515fd693bb3c8d0b |
parent 87193 | 16c4770044a8e360c391e917c4f0e6be327664c5 |
child 87195 | 766fdf473acd96b76ca7c7669a0672df9cf1633b |
push id | 22091 |
push user | bmo@edmorley.co.uk |
push date | Mon, 20 Feb 2012 12:09:20 +0000 |
treeherder | mozilla-central@b8e7474374d5 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | mrbkap |
bugs | 718543 |
milestone | 13.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/testing/mochitest/tests/SimpleTest/specialpowersAPI.js +++ b/testing/mochitest/tests/SimpleTest/specialpowersAPI.js @@ -151,30 +151,38 @@ function isXrayWrapper(x) { } // We can't call apply() directy on Xray-wrapped functions, so we have to be // clever. 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. if (!isWrappable(obj)) return obj; // No double wrapping. 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. var invocant = unwrapIfWrapped(this); var unwrappedArgs = Array.prototype.slice.call(arguments).map(unwrapIfWrapped); return wrapPrivileged(doApply(obj, invocant, unwrappedArgs)); }; @@ -188,21 +196,26 @@ function wrapPrivileged(obj) { var FakeConstructor = function() { doApply(obj, this, unwrappedArgs); }; FakeConstructor.prototype = obj.prototype; 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) { // We don't wrap primitives, so sometimes we have a primitive where we'd // expect to have a wrapper. The proxy pretends to be the type that it's // emulating, so we can just as easily check isWrappable() on a proxy as // we can on an unwrapped object. @@ -403,19 +416,16 @@ SpecialPowersAPI.prototype = { * object containing a reference to the underlying object, where all method * calls and property accesses are transparently performed with the System * Principal. Moreover, objects obtained from the wrapper (including properties * and method return values) are wrapped automatically. Thus, after a single * call to SpecialPowers.wrap(), the wrapper layer is transitively maintained. * * 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. * * - The wrapper sometimes guesses certain ES5 attributes for returned * properties. This is explained in a comment in the wrapper code above, * and shouldn't be a problem. */ wrap: wrapPrivileged,
--- a/testing/mochitest/tests/test_SpecialPowersExtension.html +++ b/testing/mochitest/tests/test_SpecialPowersExtension.html @@ -129,16 +129,23 @@ function starttest(){ noxray.__proto__ = noxray_proto; var noxray_wrapper = SpecialPowers.wrap(noxray); is(noxray_wrapper.c, 32, "Regular properties should work."); is(noxray_wrapper.a, 5, "Shadow properties should work."); is(noxray_wrapper.b, 12, "Proto properties should work."); 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(); } </script> </pre> </body> </html>