Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't function.apply() work across document boundaries in IE?

I'm seeing some strange behavior in IE trying to call functions in another page via function.apply().

Here's a simple test case:

test1.html:

<HTML>
<HEAD>
<script language="javascript" type="text/javascript">
  var opened = null;

  function applyNone() {
    opened.testFunc.apply(opened);
  }

  function applyArgs() {
    opened.testFunc.apply(opened, ["applied array"]);
  }

  function call() {
    opened.testFunc("called directly");
  }

  function remoteApply() {
    opened.testApply(["used remote apply"]);
  }

  function remoteApplyCopy() {
    opened.testApplyCopy(["used remote apply copy"]);
  }

  function openPopup() {
    opened = window.open("test2.html", "_blank");
  }
</script>
</HEAD>
<BODY>
  <a href="#" onclick="openPopup()">OPEN</a>
  <hr>
  <a href="#" onclick="applyNone()">applyNone</a>
  <a href="#" onclick="applyArgs()">applyArgs</a>
  <a href="#" onclick="call()">call</a>
  <a href="#" onclick="remoteApply()">remoteApply</a>
  <a href="#" onclick="remoteApplyCopy()">remoteApplyCopy</a>
</BODY>
</HTML>

test2.html:

<HTML>
<HEAD>
<script language="javascript" type="text/javascript">
  function testApply(args) {
    testFunc.apply(this, args);
  }

  function testApplyCopy(args) {
    var a = [];
    for(var i = 0; i < args.length; i++) {
      a.push(args[i]);
    }
    testFunc.apply(this, a);
  }

  function testFunc() {
    var s = "Got: ";
    for(var i = 0; i < arguments.length; i++) {
      s += arguments[i] + " ";
    }
    document.getElementById("output").innerHTML += s + "<BR>";
  }
</script>
</HEAD>
<BODY>
  Hi there
  <div id="output"/>
</BODY>
</HTML>

In firefox and chrome all methods work properly.

In IE (tested in 6, 7, and 8) all but the applyArgs() and remoteApply() methods work as expected.

applyArgs() gives a "JScript object expected" error when it tries calling apply (test1.html line 11).

remoteApply() gives the same "JScript object expected" error when it tries calling apply (test2.html line 5).

Problem is, I need to be able to use apply(). I can get around the issue by doing something like the remoteApplyCopy() mechanism, but I'm trying to avoid that. Why doesn't apply() just work?

like image 692
Herms Avatar asked Jul 09 '09 14:07

Herms


1 Answers

You need to have the arrays created in the other window, because each window has its own Array constructor. I think this will work.

Add this function to test2.html:

function getEmptyArray() {
    return new Array();
}

And this function to test1.html:

Array.prototype.cloneToRemote = function (win) {
    var newArray = win.getEmptyArray();
    for (var i = 0; i < this.length; i++)
    {
        newArray.push(this[i]);
    }
    return newArray;
}

Then do this:

function applyArgs() {
    opened.testFunc.apply(opened, ["applied array"].cloneToRemote(opened));
}

Note, it seems like you should be able to do

var newArray = new win.Array();

within the test1.html cloneToRemote() function, but I couldn't make that work. If you could do that, you could get rid of the new getEmptyArray() function in test2.html.

like image 110
edsoverflow Avatar answered Oct 13 '22 19:10

edsoverflow