views:

848

answers:

5

I'm writing a piece of code that requires the DOM of a website to remain frozen while arbitrary JavaScript runs. Attributes changing is fine but I can't have anything changing the original tag structure of the page!

I know in JavaScript there are a base number of functions that can modify the DOM:

appendChild( nodeToAppend )
cloneNode( true|false )
createElement( tagName )
createElemeentNS( namespace, tagName )
createTextNode( textString )
innerHTML
insertBefore( nodeToInsert, nodeToInsertBefore )
removeChild( nodetoRemove )
replacechild( nodeToInsert, nodeToReplace )

My initial thought was simply to overwrite these functions as no ops:

>>> document.write('<p>Changing your DOM. Mwwhaha!</p>')
>>> document.write = function() {}
>>> document.write('<p>No-op now!</p>')

While it's easy to do this for the document object the DOM modification functions can be called from many different JavaScript objects! If I could overwrite these functions at top level perhaps it would work?

Update from sktrdie:

>>> HTMLElement.prototype.appendChild = function(){}
>>> $("a").get(0).appendChild(document.createElement("div"))
# Still works argh.
>>> HTMLAnchorElement.prototype.appendChild = function(){}
>>> $("a").get(0).appendChild(document.createElement("div"))
# No-op yeah!

So it would seem I could just gather the constructors of all DOM elements and run over them putting in no-ops but that still seems pretty messy ...

How can I protect the DOM from modification from arbitrary JavaScript?

A: 

Don't do this. Use a whitelist. Please.

brian
A: 

You could possibly put everything in a <div> tag, and hide that tag, replacing it with another that says 'Loading..'. Then after it has loaded you could hide the loading <div> and replace it with the original.

Click Upvote
+1  A: 

Have you tried HTMLElement.prototype.appendChild = function(){} to overwrite DOM methods at a higher level?

Luca Matteis
This is close. The problem is HTMLDivElement / HTMLAnchorElement etc. will not be effected by this ...
jb
I don't think IE has this built into their DOM. Maybe the later versions but I remember IE6 not having it.
bucabay
A: 

There is no way to do this. I did a couple of tests and no matter how I tried to overwrite these methods they remain. I believe that they are implemented in a higher level than executable javascript can access, so you can't really touch them.

Salty
A: 

While this is really hackish, the only way to maintain the current DOM structure is to store a "snapshot" of the DOM and check it periodically.

//place in anonymous function to prevent global access
(function() {
  //storing the whole DOM as objects would be ideal, but too memory intensive, so a string will have to do.
  var orignalDOM = document.body.innerHTML;

  var checkDOM = fuction() {
    if (document.body.innerHTML != originalDOM)  document.body.innerHTML = originalDOM
    //check that the code is running
    if (arbitraryCodeIsRunning)  setTimeout("checkDOM", 100);
  }
  checkDOM();
})();

Probably not what your looking for, but after some testing it's the only way I can think of to maintain DOM structure regardless.

tj111