Steps to reproduce:
- Open the user script from this gist: https://gist.github.com/Ventero/c75d29c0dbab12c9a2db - it doesn't matter whether the installation of the script is finished or not, as long as the install dialog showed up. Note that the
@required script contains an alert("Github").
- Install the following user script: http://dump.ventero.de/greasemonkey/relative_require/script/requirefail2.user.js - this script contains the same
@require directive as the previous script, but since it's installed from a different location, this time http://dump.ventero.de/greasemonkey/relative_require/c78475b522fe3a8a699e31312561075c2c20c742/require.js should be downloaded - which contains an alert("Not Github").
- Load any website.
Expected result: alert("Not Github") is executed.
Actual result: alert("Github") is executed.
The reason for this is that a nsIURI object is passed to the memoized uriFromUrl. The memoization uses essentially uneval(arguments) as cache key, which works fine as long as the arguments are primitives. For an nsIURI, uneval(uri) however results in ({}). This then leads to an incorrect cached value being returned for the @required URL during installation of the second script.
I can see 3 options on how to fix this issue:
- Don't memoize
uriFromUrl. I don't think this is a good idea though, as this function is called quite often (for me, it's several hundred times per minute). Almost all calls are without a second argument or with a string though.
- Memoize only calls with a primitive or without a second argument. For a possible patch, see Ventero@729ab67.
- Convert all calling sites that pass a uri to pass
uri.spec instead (looks like there's only 4 such callers). But this causes unnecessary overhead, as the spec strings have to be converted back to a URI inside uriFromUrl again.
Steps to reproduce:
@required script contains analert("Github").@requiredirective as the previous script, but since it's installed from a different location, this time http://dump.ventero.de/greasemonkey/relative_require/c78475b522fe3a8a699e31312561075c2c20c742/require.js should be downloaded - which contains analert("Not Github").Expected result:
alert("Not Github")is executed.Actual result:
alert("Github")is executed.The reason for this is that a
nsIURIobject is passed to the memoizeduriFromUrl. The memoization uses essentiallyuneval(arguments)as cache key, which works fine as long as the arguments are primitives. For annsIURI,uneval(uri)however results in({}). This then leads to an incorrect cached value being returned for the@required URL during installation of the second script.I can see 3 options on how to fix this issue:
uriFromUrl. I don't think this is a good idea though, as this function is called quite often (for me, it's several hundred times per minute). Almost all calls are without a second argument or with a string though.uri.specinstead (looks like there's only 4 such callers). But this causes unnecessary overhead, as the spec strings have to be converted back to a URI insideuriFromUrlagain.