V8 crashing with ‘Uncaught RangeError: Maximum call stack size exceeded’

While working with V8 in another process, it kept crashing at initialization with the message ‘Uncaught RangeError: Maximum call stack size exceeded’. I wasn’t doing anything big, just initialization.
After about 3 hour of debugging, I found out what was wrong. Normally, V8 will assume that you have no more than 512KB of stack space. To prevent stack overflows, it will take a stack address, substract 512kb from it, and remember that address. If it ever passes that address, it’ll throw a RangeError.

The problem lies in the fact that the program I was working with had a stack somewhere around 0x60000 or 384kb. V8 then substracts 512 from that, but instead of getting a nice stack-boundary, it ends up with an incredibly big number due to integer underflow. The next time it checks the stack, it compares the stack address (still somewhere around 0x60000) with it’s calculated stack limited (which, due to the underflow, is about 0xFFFE0000), and assumes it has a stack overflow.

To fix this, I had to manually set the stack limit. Basically, the following code takes a random stack address, divides it by 2, and uses that as the lower-limit to the stack:

	v8::ResourceConstraints rc;
	rc.set_stack_limit((uint32_t *)(((uint32_t)&rc)/2));
	v8::SetResourceConstraints(&rc);

New Live Messenger APIs

While the old messenger APIs have been steadily crumbling the past few versions, and the latest WLM10 beta having made it nearly useless, I was amazed to find several new APIs.
One of them is the “LivePlatform” API, which seems to be what messenger is using to retrieve the contact list and social news.
I don’t have time to investigate this fully, but I did get to put together a small demo. To try it, create a new console application in C#, add C:\Program Files\Windows Live\Contacts\LivePlatform.dll as a reference, and put in the following code in Main:

 LivePlatform.LivePlatformFactory factory=new LivePlatform.LivePlatformFactory();
            LivePlatform.ILiveIdentityCollection ids = factory.IdentityService.CachedIdentities;
            System.Console.WriteLine("Cached identities");
            for (int i = 0; i < ids.Count; i++)
            {
                LivePlatform.ILiveIdentity id = ids[i];
                if (id.HasPassword)
                    System.Console.WriteLine("\t"+id.Username);
            }
            System.Console.Write("Username: ");
            string szUsername = System.Console.ReadLine();
            LivePlatform.ILiveIdentity found = null;
            for (int i = 0; i < ids.Count; i++)
            {
                LivePlatform.ILiveIdentity id = ids[i];
                if (id.HasPassword && id.Username.ToLower().Equals(szUsername.ToLower()))
                {
                    found = id;
                    break;
                }
            }
            string szPassword = "";
            if (found == null)
            {
                System.Console.Write("Password: ");
                szPassword = System.Console.ReadLine();
            }
            platform=(found==null)?factory.CreateEx(szUsername,szPassword):factory.Create(found);
            platform.Config["BlockingSignin"] = true; //Don't set this to make Signin non-blocking. You'll have to wire up events to listen for OnReady before you do anything, though.
            platform.Signin(null);
            System.Console.WriteLine("Full name: "+platform.Me.FullName);
            LivePlatform.ILiveObjectCollection query = platform.Query("type(contact)");
            System.Console.WriteLine(String.Format("Contacts: {0}", query.Count));
            for (int c = 0; c < query.Count; c++)
            {
                LivePlatform.ILiveObject obj = query[c];
                LivePlatform.ILiveContact contact = obj as LivePlatform.ILiveContact;
                System.Console.WriteLine(String.Format("{0} ({1})", contact.FullName,(contact.Emails.Count>0)?contact.Emails[0].Address:"none"));
            }
            System.Console.WriteLine("Press enter to quit");
            System.Console.ReadLine();

It’ll print your full name, as well as your full contact list. Also note that if you added your facebook account, those contacts will show up too.
Some other queries I saw when debugging messenger:

type(invite)
type(contact) and contacts:canHideFrom(true)
type(contact)
type(contact) and contacts:isHidingFrom(true) and contancts:canHideFrom(true)
type(contact)
type(circle)
type(category)
type(category) and contacts:isfavorite(true)
type(contact) and contacts:isonline(true)
type(category) and contacts:isfavorite(true)

I believe that hooking this API in messenger might allow for some pretty cool tricks, for example something like BuddyFuse.

As a final note, I’d like to say that I’m posting this because I’m hoping more sharing might make the messenger community more like it once was. If you find out more about this API, or other new APIs, please be so kind to share them too so a new sharing eco-system might emerge. Thanks.

EDIT: Added cached identities.