Bug Tracker

Opened 13 years ago

Closed 13 years ago

Last modified 12 years ago

#6842 closed bug (fixed)

Expando Collision Possible With noConflict()

Reported by: SlexAxton Owned by: SlexAxton
Priority: high Milestone: 1.5
Component: data Version: 1.4.3
Keywords: expando, collision, noconflict, needsreview Cc:
Blocked by: Blocking:

Description

If a page has two copies of jQuery, the jQuery expando property can still collide between these two copies even if noConflict is called. This has always been the case, but it hasn't really been feasible until some of the new V8 builds.

The expando is based off of the current millisecond:

var expando = "jQuery" + now()

This reference is available on the jQuery object, but private references exist, so it's not entirely patchable at this point, from the outside.

This would presumably be bad anywhere that unique expandos are necessary.

Test Case Here: http://jsbin.com/ifone

Proof that it's getting too close to ignore: http://slexaxton.com/pix/afe1.png

Change History (11)

comment:1 Changed 13 years ago by john

Any suggestions as to an alternative? The random number generator may get us part of the way there - but I don't like having a continued random chance of a collision happening.

It might also be worthwhile to change the 'jQuery' bit to something like 'jq' + jQuery.fn.jquery to help differentiate between versions of jQuery.

comment:2 in reply to:  1 Changed 13 years ago by SlexAxton

Replying to john:

Any suggestions as to an alternative? The random number generator may get us part of the way there - but I don't like having a continued random chance of a collision happening.

It might also be worthwhile to change the 'jQuery' bit to something like 'jq' + jQuery.fn.jquery to help differentiate between versions of jQuery.

This really only matters during the use of noConflict (otherwise a lot more than this can conflict...), so perhaps changing up noConflict a bit to accept a custom expando prefix.

var my$ = jQuery.noConflict(true, 'mycoolprefix');

valid option?

comment:3 Changed 13 years ago by cowboy

You could do something like this, instead of var expando = "jQuery" + now():

var jq = window.jQuery || window.$,
  expando = "jQuery" + (
    ( jq && jq.expando && +jq.expando.replace( /\D/g, "" ) || 0 ) + 1
  );

comment:4 Changed 13 years ago by SlexAxton

I'd love for the solution to not be susceptible to collisions, even though they are even more rare than this one.

The problem with your solution, Ben, is that if someone has done noConflict(true), then a conflict is still possible. That's pretty rare, but I have run into it.

comment:5 Changed 13 years ago by SlexAxton

I have submitted a patch for this on github: http://github.com/jquery/jquery/pull/29

comment:6 Changed 13 years ago by snover

Milestone: 1.4.31.5
Priority: high
Status: newopen
Version: 1.4.21.4.3

comment:7 Changed 13 years ago by addyosmani

Keywords: needsreview added

comment:8 Changed 13 years ago by SlexAxton

The most recent pull request after github discussion is here:

https://github.com/jquery/jquery/pull/50

comment:9 Changed 13 years ago by SlexAxton

Owner: set to SlexAxton
Status: openassigned

comment:10 Changed 13 years ago by Alex Sexton

Resolution: fixed
Status: assignedclosed

Changed the expando string to use a random number instead of the time, so collisions become less likely. Also added jQuery version to instantly differentiate separate versions of jQuery (a common use case for noConflict, etc, when two jQuery instances are on the page). Fixes #6842.

Changeset: faabb2c31883deabaddd5642eb5e708b5802f2b0

comment:11 Changed 13 years ago by Alex Sexton

Changed the expando string to use a random number instead of the time, so collisions become less likely. Also added jQuery version to instantly differentiate separate versions of jQuery (a common use case for noConflict, etc, when two jQuery instances are on the page). Fixes #6842.

Changeset: faabb2c31883deabaddd5642eb5e708b5802f2b0

Note: See TracTickets for help on using tickets.