tmpvar/jsdom — Issue #382: Multiple elements with same ID breaks getElementById
Author: deitch
Created: 2012-01-03 11:45:23+00:00
State: open

Summary: If you have two elements by the same name, then remove one, you can no longer use getElementById to get the original one, which breaks jQuery and all other frameworks too.

Solution: make document._ids a hash to array of objects, rather than hash to object.

Detail: jsdom keeps a hash of all elements by ID on its document as document._ids

When you add an element, it extracts the ID, and saves a reference to the object there. E.g. if you add
This is foo

then jsdom will have
document._ids["foo"] = spanObjectReference;

When you remove an element, it just does

delete document._ids["foo"];

Makes sense. The problem is that in HTML you can have more than one element with the same ID. You are not supposed to, but you can, and all browsers should handle it. It is quite common when doing templating and transitioning, that I might create a new element, make its innerHTML the same as my old, then remove the old. So for a short time, I have two elements, both with the same ID. But when I remove one of them, document._ids loses them both. This means I no longer have a reference to the single valid one.

The fix should be to have document._ids have a hash to array:

document._ids["foo"] = [obj1, obj2, ... ]

When adding in _attach (level1/core.js#544), just push; when removing in _detach (level1/core.js#558), slice if the element matches 'this'.

Also need to fix in level1/core.js #1120, #531; level2/core.js #516, #631.

Happy to fork and fix with pull request, if you will pull it in quickly.

Thanks.