This project is read-only.

.NET objects equality on JS side

May 7, 2013 at 2:39 PM
I have an issue. I execute following script in my project (just a sample code to better illustrate the problem):
var d1 = document.documentElement;
var d2 = document.getElementsByTagName('html')[0];

alert(d1 == d2);
Alert display False as the result of the comparison. But d1 and d2 hold references for same .NET side object. But on JS side I have 2 different object (based on comparison result).
Does anybody have an idea on how I can alter the library so "d1 == d2" would actually yield True as a result?
May 7, 2013 at 5:35 PM
Does it have to be "d1 == d2", or can you use "d1.Equals(d2)"? It looks like you're implementing your own HTML DOM, so you're probably running random web scripts that require "d1 == d2". Is that correct?
May 7, 2013 at 6:47 PM
Yes, you are correct. I'm running various scripts against my DOM structure. And I can not control content for all of them, so it has to be ==. Along with our custom scripts we need some frameworks to be working (this particular issue I found when working on jQuery).
May 7, 2013 at 9:20 PM
It looks like the library re-wraps each .NET object (via JavascriptInterop::WrapObject) every time it hands it off to JS. For it to do what you want, it would have to be able to bind to an existing wrapper instead, if available. This would require some kind of wrapper cache at this layer. Building such a thing might be tricky; for one thing, it would probably have to hold everything weakly to avoid interfering with GC.
May 8, 2013 at 8:12 AM
But what objects I have to cache? From what I understand there are 3 objects created from each wrapped .NET object:
  • ObjectTemplate (with context->GetObjectWrapperTemplate())
  • v8::External (which is set to internal field 0 of the object template)
  • JavascriptExternal (wrapped inside v8::External object)
    I've tried to reuse JavascriptExternal instances with existing cache JavascriptContext::mExternals (I've added lookup before creating new instance). But it didn't solve the problem. Should I cache v8::External instances and ObjectTemplate too? Or just v8::External caching will be enough? I'm not really sure how v8 performs external object comparison.
May 8, 2013 at 2:30 PM
I think "d1 == d2" checks whether d1 and d2 actually refer to the same JS object. Therefore JavascriptInterop::WrapObject needs to return the same JS object every time it's called with the same .NET object as the argument, until that JS object is removed via GC. So basically you need a dictionary that maps .NET objects to JS objects but doesn't interfere with GC on either side. I'm guessing you'll need one of these per JavascriptContext. Good luck!
May 8, 2013 at 5:58 PM
Thanks. Will try to dig around that function.