/*
 * Copyright 2008 Google Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

#import "WebScriptSessionHandler.h"
#import "InvokeMessage.h"
#import "ObjectFunctions.h"
#import "ServerMethods.h"
#import "TrackingData.h"
#import "scoped_ptr.h"


WebScriptSessionHandler::WebScriptSessionHandler(HostChannel* channel,
                                                 JSGlobalContextRef contextRef,
                                                 CrashHandlerRef crashHandler) : 
SessionData(channel, contextRef, this), jsObjectId(1), crashHandler(crashHandler) {

  JSClassDefinition def = kJSClassDefinitionEmpty;
  def.className = "JavaObject";
  def.hasProperty = JavaObjectHasProperty;
  def.callAsFunction = JavaObjectCallAsFunction;
  def.finalize = JavaObjectFinalize;
  def.getProperty = JavaObjectGetProperty;
  def.setProperty = JavaObjectSetProperty;
  javaObjectWrapperClass = JSClassCreate(&def);
  JSClassRetain(javaObjectWrapperClass);
  
  // Get the String constructor function to tell Strings from other Objects
  JSStringRef stringString = JSStringCreateWithUTF8CString("String");
  JSValueRef stringConstructorValue = JSObjectGetProperty(contextRef,
                                                          JSContextGetGlobalObject(contextRef),
                                                          stringString, NULL);
  stringConstructor = JSValueToObject(contextRef, stringConstructorValue, NULL);
  JSValueProtect(contextRef, stringConstructor);
  JSStringRelease(stringString);
  
  // Call out to the utility __gwt_makeResult function to create the return array
  JSStringRef makeResultString = JSStringCreateWithUTF8CString("__gwt_makeResult");
  JSValueRef makeResultValue = JSObjectGetProperty(contextRef, JSContextGetGlobalObject(contextRef), makeResultString, NULL);
  JSStringRelease(makeResultString);
  
  if (!JSValueIsObject(contextRef, makeResultValue)) {
    crashHandler->crash(__PRETTY_FUNCTION__, "Could not find __gwt_makeResult");
  } else {
    makeResultFunction = JSValueToObject(contextRef, makeResultValue, NULL);
    JSValueProtect(contextRef, makeResultFunction);
  }
  
  pthread_mutexattr_t mutexAttrs;
  pthread_mutexattr_init(&mutexAttrs);
  // This behaves basically like the Java synchronized keyword
  pthread_mutexattr_settype(&mutexAttrs, PTHREAD_MUTEX_RECURSIVE);
  pthread_mutex_init(&javaObjectsLock, &mutexAttrs);
  pthread_mutexattr_destroy(&mutexAttrs);
}

WebScriptSessionHandler::~WebScriptSessionHandler() {
  std::map<int, JSObjectRef>::iterator i;
  
  pthread_mutex_lock(&javaObjectsLock);
  while ((i = javaObjectsById.begin()) != javaObjectsById.end()) {
    JavaObjectFinalize(i->second);
  }
  pthread_mutex_unlock(&javaObjectsLock);
  
  for (i = jsObjectsById.begin(); i != jsObjectsById.end(); i++) {
    JSObjectRef ref = i->second;
    delete static_cast<TrackingDataRef>(JSObjectGetPrivate(ref));
    JSObjectSetPrivate(ref, NULL);
    JSValueUnprotect(contextRef, i->second);
  }
  
  JSClassRelease(javaObjectWrapperClass);
  
  JSValueUnprotect(contextRef, stringConstructor);
  JSValueUnprotect(contextRef, makeResultFunction);
  
  JSGarbageCollect(contextRef);
  pthread_mutex_destroy(&javaObjectsLock);
}

void WebScriptSessionHandler::freeJavaObjects() {
  pthread_mutex_lock(&javaObjectsLock);
  int idCount = javaObjectsToFree.size();
  if (idCount == 0) {
    pthread_mutex_unlock(&javaObjectsLock);
    return;
  }
  
  int ids[idCount];
  std::set<int>::iterator it = javaObjectsToFree.begin();
  for (int i = 0; i < idCount; it++) {
    ids[i++] = *it;
  }
  if (!ServerMethods::freeJava(*channel, this, idCount, ids)) {
    Debug::log(Debug::Error) << "Unable to free Java ids" << Debug::flush;
  } else {
    Debug::log(Debug::Debugging) << "Freed " << idCount << " Java ids" << Debug::flush;
  }
  javaObjectsToFree.clear();
  pthread_mutex_unlock(&javaObjectsLock);
}

void WebScriptSessionHandler::freeValue(HostChannel& channel, int idCount, const int* ids) {
  Debug::log(Debug::Spam) << "freeValue freeing " << idCount << " js objects" << Debug::flush;
  if (idCount == 0) {
    return;
  }
  
  for (int i = 0; i < idCount; i++) {
    int objId = ids[i];
    
    std::map<int, JSObjectRef>::iterator i = jsObjectsById.find(objId);
    if (i == jsObjectsById.end()) {
      Debug::log(Debug::Error) << "Unknown object id " << objId << Debug::flush;
      continue;
    }
    
    JSObjectRef ref = i->second;
    jsObjectsById.erase(objId);
    jsIdsByObject.erase(ref);
    JSValueUnprotect(contextRef, ref);
  }
  Debug::log(Debug::Debugging) << "Freed " << idCount << " JS objects" << Debug::flush;
}

void WebScriptSessionHandler::initiateAutodestructSequence(const char* functionName, const char* message) {
  crashHandler->crash(functionName, message);
}

bool WebScriptSessionHandler::invoke(HostChannel& channel, const Value& thisObj,
                                    const std::string& methodName,
                                    int numArgs, const Value* args, Value* returnValue) {
  Debug::log(Debug::Spam) << "invoke " << methodName << Debug::flush;

  JSValueRef argsJS[numArgs];
  JSValueRef localException = NULL;
  JSStringRef methodNameJS = JSStringCreateWithUTF8CString(methodName.c_str());    
  JSObjectRef thisObjJs;
  
  if (thisObj.isNull()) {
    thisObjJs = JSContextGetGlobalObject(contextRef);
  } else {
    thisObjJs = (JSObjectRef) makeValueRef(thisObj);
  }
  
  JSValueRef functionValueJS = JSObjectGetProperty(contextRef, JSContextGetGlobalObject(contextRef),
                                                   methodNameJS, &localException);
  JSStringRelease(methodNameJS);
  
  if (!JSValueIsObject(contextRef, functionValueJS)) {
    char message[512];
    snprintf(message, sizeof(message), "Could not find method for property name %s on %s", methodName.c_str(), thisObj.toString().c_str());
    makeExceptionValue(*returnValue, message);
    return true;
  }
  
  JSObjectRef functionJS = JSValueToObject(contextRef, functionValueJS,
                                           &localException);
  if (localException) {
    makeValue(*returnValue, localException);
    return true;
  }
  
  // Convert the arguments
  for (int i = 0; i < numArgs; i++) {
    argsJS[i] = makeValueRef(args[i]);
  }
  
  JSValueRef retVal = JSObjectCallAsFunction(contextRef, functionJS,
                                             thisObjJs, numArgs, argsJS,
                                             &localException);
  
  // It's safe to free remote objects before sending an Invoke or a Return message
  freeJavaObjects();
  
  if (localException) {
    Debug::log(Debug::Spam) << "Returning exception to server" << Debug::flush;
    makeValue(*returnValue, localException);
    return true;
  } else {
    makeValue(*returnValue, retVal);
    return false;
  }
}

bool WebScriptSessionHandler::invokeSpecial(HostChannel& channel, SpecialMethodId method, int numArgs,
                                            const Value* const args, Value* returnValue) {
  Debug::log(Debug::Spam) << "invokeSpecial " << method << Debug::flush;
  switch (method) {
    case GetProperty:
    {
      int objId = args[0].getInt();
      std::map<int, JSObjectRef>::iterator i = jsObjectsById.find(objId);
      if (i == jsObjectsById.end()) {
        char message[50];
        snprintf(message, sizeof(message), "Unknown object id %i", objId);
        makeExceptionValue(*returnValue, message);
        return true;
      }
      
      JSObjectRef jsObj = i->second;
      if (args[1].isString()) {
        JSStringRef asString = JSValueToStringCopy(contextRef, jsObj, NULL);
        int maxLength = JSStringGetMaximumUTF8CStringSize(asString);
        scoped_array<char> asChars(new char[maxLength]);
        JSStringGetUTF8CString(asString, asChars.get(), maxLength);
        
        JSValueRef localException = NULL;
        JSStringRef str = JSStringCreateWithUTF8CString(args[1].getString().c_str());
        JSValueRef value = JSObjectGetProperty(contextRef, jsObj, str, &localException);
        JSStringRelease(str);
        if (localException) {
          makeValue(*returnValue, localException);
          return true;
        } else {
          makeValue(*returnValue, value);
          return false;
        }
      } else if (args[1].isInt()) {
        JSValueRef localException = NULL;
        JSValueRef value = JSObjectGetPropertyAtIndex(contextRef, jsObj, args[1].getInt(), &localException);
        
        if (localException) {
          makeValue(*returnValue, localException);
          return true;
        } else {
          makeValue(*returnValue, value);
          return false;
        }
      } else {
        char message[50];
        snprintf(message, sizeof(message), "Unhandled argument type %s for getProperty", args[1].toString().c_str());
        makeExceptionValue(*returnValue, message);
        return true;
      }
    }
    default:
      Debug::log(Debug::Error) << "Unhandled invokeSpecial " << method << Debug::flush;
      makeExceptionValue(*returnValue, "Unhandled invokeSpecial");
      return true;
  }  
}

JSValueRef WebScriptSessionHandler::javaFunctionCallbackImpl (int dispatchId,
                                                              JSObjectRef thisObject,
                                                              size_t argumentCount,
                                                              const JSValueRef arguments[],
                                                              JSValueRef* exception){
  /*
   * NB: Because throwing exceptions in JavaScriptCore is trivial, we don't rely
   * on any special return values to indicate that an exception is thrown, we'll simply
   * throw the exception.
   */
  Debug::log(Debug::Debugging) << "Java method " << dispatchId << " invoked" << Debug::flush;
  
  /*
   * If a JS function is evaluated without an meaningful this object or the global
   * object is implicitly used as the this object, we'll assume that the
   * Java-derived method is static, and send a null this object to the server
   */
  Value thisValue;
  if (JSValueIsEqual(contextRef, thisObject, JSContextGetGlobalObject(contextRef), NULL)) {
    thisValue = Value();
    thisValue.setNull();
  } else {
    makeValue(thisValue, thisObject);
  }
  
  // Argument conversion is straightforward
  Value args[argumentCount];
  for (int i = 0; i < argumentCount; i++) {
    makeValue(args[i], arguments[i]);
  }
  
  if (!InvokeMessage::send(*channel, thisValue, dispatchId,
                           argumentCount, args)) {
    initiateAutodestructSequence(__PRETTY_FUNCTION__, "Unable to send invocation message");
    *exception = makeException("Unable to send invocation message");
    return JSValueMakeUndefined(contextRef);
  }
  
  scoped_ptr<ReturnMessage> ret(channel->reactToMessagesWhileWaitingForReturn(sessionHandler));
  
  if (!ret.get()) {
    initiateAutodestructSequence(__PRETTY_FUNCTION__, "Unable to receive return message");
    *exception = makeException("Unable to receive return message");
    return JSValueMakeUndefined(contextRef);
  }
  
  Value v = ret->getReturnValue();
  
  JSValueRef toReturn;
  if (ret->isException()) {
    *exception = makeValueRef(v);
    toReturn = JSValueMakeUndefined(contextRef);
  } else {
    toReturn = makeValueRef(v);
  }
  
  JSValueRef makeResultArguments[] = {JSValueMakeBoolean(contextRef, false), toReturn};
  return JSObjectCallAsFunction(contextRef, makeResultFunction, NULL, 2, makeResultArguments, exception);
}

void WebScriptSessionHandler::javaObjectFinalizeImpl(int objId) {
  if (pthread_mutex_lock(&javaObjectsLock)) {
    Debug::log(Debug::Error) << "Unable to acquire javaObjectsLock in thread " << pthread_self() << " " << __PRETTY_FUNCTION__ << Debug::flush;
    initiateAutodestructSequence(__PRETTY_FUNCTION__, "Unable to acquire javaObjectsLock");
    return;
  }
  javaObjectsById.erase(objId);
  javaObjectsToFree.insert(objId);
  if (pthread_mutex_unlock(&javaObjectsLock)) {
    Debug::log(Debug::Error) << "Unable to release javaObjectsLock in thread " << pthread_self() << " " << __PRETTY_FUNCTION__ << Debug::flush;
    initiateAutodestructSequence(__PRETTY_FUNCTION__, "Unable to release javaObjectsLock");
  }
}

JSValueRef WebScriptSessionHandler::javaObjectGetPropertyImpl (TrackingDataRef tracker, JSObjectRef object,
                                                               JSStringRef propertyName, JSValueRef* exception) {
  *exception = NULL;
  
  // Convert the name
  int maxLength = JSStringGetMaximumUTF8CStringSize(propertyName);
  scoped_array<char> propertyNameChars(new char[maxLength]);
  JSStringGetUTF8CString(propertyName, propertyNameChars.get(), maxLength);
  JSValueRef toReturn;  
  
  if (!strcmp(propertyNameChars.get(), "toString")) {
    // We'll call out to the JSNI tear-off support function
    JSStringRef tearOffName =JSStringCreateWithUTF8CString("__gwt_makeTearOff");
    JSValueRef makeTearOffValue = JSObjectGetProperty(contextRef, JSContextGetGlobalObject(contextRef), tearOffName, exception);
    JSStringRelease(tearOffName);
    if (*exception) {
      return JSValueMakeUndefined(contextRef);
    }    
    
    JSObjectRef makeTearOff = JSValueToObject(contextRef, makeTearOffValue, exception);
    if (*exception) {
      return JSValueMakeUndefined(contextRef);
    }
    
    JSValueRef arguments[3];
    arguments[0] = object;
    arguments[1] = JSValueMakeNumber(contextRef, 0);
    arguments[2] = JSValueMakeNumber(contextRef, 0);
    toReturn = JSObjectCallAsFunction(contextRef, makeTearOff, JSContextGetGlobalObject(contextRef), 3, arguments, exception);
  } else {
    char* endptr;
    int dispatchId = strtol(propertyNameChars.get(), &endptr, 10);
    
    if (*endptr != '\0') {
      Debug::log(Debug::Error) << "Unable to parse dispatch id " << propertyNameChars.get() << Debug::flush;
      *exception = makeException("Unable to parse dispatch id");
    } else if (dispatchId < 0) {
      Debug::log(Debug::Error) << "Dispatch ids may not be negative" << Debug::flush;
      *exception = makeException("Dispatch ids may not be negative");
    } else {
      Value v = ServerMethods::getProperty(*channel, this, tracker->getObjectId(), dispatchId);
      toReturn = makeValueRef(v);
    }
  }
  
  return toReturn;
}

bool WebScriptSessionHandler::javaObjectHasPropertyImpl (TrackingDataRef tracker, JSObjectRef object, JSStringRef propertyName) {
  // The property name must either be "toString" or a number
  int maxLength = JSStringGetMaximumUTF8CStringSize(propertyName);
  scoped_array<char> propertyNameChars(new char[maxLength]);
  JSStringGetUTF8CString(propertyName, propertyNameChars.get(), maxLength);
  if (!strcmp(propertyNameChars.get(), "toString")) {
    return true;
  }
  
  char* endptr;
  int dispatchId = strtol(propertyNameChars.get(), &endptr, 10);
  
  if (*endptr != '\0') {
    return false;
  } else if (dispatchId < 0) {
    return false;
  } else {
    return true;
  }
}

bool WebScriptSessionHandler::javaObjectSetPropertyImpl (TrackingDataRef tracker, JSObjectRef object,
                                                         JSStringRef propertyName, JSValueRef jsValue,
                                                         JSValueRef* exception) {
  int maxLength = JSStringGetMaximumUTF8CStringSize(propertyName);
  scoped_array<char> propertyNameChars(new char[maxLength]);
  JSStringGetUTF8CString(propertyName, propertyNameChars.get(), maxLength);
  Value value;
  
  char* endptr;
  int dispatchId = strtol(propertyNameChars.get(), &endptr, 10);
  
  if (*endptr != '\0') {
    // TODO Figure out the right policy here; when we throw a Java object, JSCore wants to
    // add expandos to record stack information.  It would be possible to map the limited
    // number of properties into a synthetic causal exception in the exception being thrown.
  } else if (dispatchId < 0) {
    // Do nothing.
    Debug::log(Debug::Error) << "Dispatch ids may not be negative" << Debug::flush;
    *exception = makeException("Dispatch ids may not be negative");
  } else {
  
    makeValue(value, jsValue);
    
    if (!ServerMethods::setProperty(*channel, this, tracker->getObjectId(), dispatchId, value)) {
      char message[50];
      snprintf(message, sizeof(message), "Unable to set value object %i dispatchId %i", tracker->getObjectId(), dispatchId);
      *exception = makeException(message);
    }
  }
  
  // true means to not try to follow the prototype chain; not an indication of success
  return true;
}

void WebScriptSessionHandler::loadJsni(HostChannel& channel, const std::string& js) {
  Debug::log(Debug::Spam) << "loadJsni " << js << Debug::flush;
  JSValueRef localException = NULL;
  
  JSStringRef script = JSStringCreateWithUTF8CString(js.c_str());
  JSEvaluateScript(contextRef, script, NULL, NULL, NULL, &localException);
  JSStringRelease(script);
  
  if (localException) {
    // TODO Exception handling
    Debug::log(Debug::Error) << "Exception thrown during loadJsni" << Debug::flush;
  } else {
    Debug::log(Debug::Spam) << "Success" << Debug::flush;
  }
}

JSValueRef WebScriptSessionHandler::makeException(const char* message) {
  JSValueRef localException = NULL;
  JSObjectRef global = JSContextGetGlobalObject(contextRef);
  
  JSStringRef errorName = JSStringCreateWithUTF8CString("Error");
  JSValueRef errorValue = JSObjectGetProperty(contextRef, global, errorName, &localException);
  JSStringRelease(errorName);
  
  if (!JSValueIsObject(contextRef, errorValue)) {
    initiateAutodestructSequence(__PRETTY_FUNCTION__, "Could not get reference to Error");
    return JSValueMakeUndefined(contextRef);
  }
  
  JSObjectRef errorObject = (JSObjectRef) errorValue;
  
  if (!JSObjectIsFunction(contextRef, errorObject)) {
    initiateAutodestructSequence(__PRETTY_FUNCTION__, "Error was not a function");
    return JSValueMakeUndefined(contextRef);
  }
  
  JSValueRef args[1];
  JSStringRef messageJs = JSStringCreateWithUTF8CString(message);
  args[0] = JSValueMakeString(contextRef, messageJs);
  JSStringRelease(messageJs);
  
  return JSObjectCallAsConstructor(contextRef, errorObject, 1, args, &localException);
}

void WebScriptSessionHandler::makeExceptionValue(Value& value, const char* message) {
  makeValue(value, makeException(message));
}

JSObjectRef WebScriptSessionHandler::makeJavaWrapper(int objId) {
  Debug::log(Debug::Spam) << "Creating wrapper for Java object " << objId << Debug::flush;
  
  TrackingDataRef data = new TrackingData(this, objId);
  return JSObjectMake(contextRef, javaObjectWrapperClass,
                      const_cast<TrackingData*>(data));
}

JSValueRef WebScriptSessionHandler::makeValueRef(const Value& v) {
  std::map<int, JSObjectRef>::iterator i;
  switch (v.getType()) {
    case Value::NULL_TYPE:
      return JSValueMakeNull(contextRef);
      
    case Value::BOOLEAN:
      return JSValueMakeBoolean(contextRef, v.getBoolean());
      
    case Value::BYTE:
      return JSValueMakeNumber(contextRef, v.getByte());
      
    case Value::CHAR:
      return JSValueMakeNumber(contextRef, v.getChar());
      
    case Value::SHORT:
      return JSValueMakeNumber(contextRef, v.getShort());
      
    case Value::INT:
      return JSValueMakeNumber(contextRef, v.getInt());
      
    case Value::LONG:
      return JSValueMakeNumber(contextRef, v.getLong());
      
    case Value::FLOAT:
      return JSValueMakeNumber(contextRef, v.getFloat());
      
    case Value::DOUBLE:
      return JSValueMakeNumber(contextRef, v.getDouble());
      
    case Value::STRING:
    {
      std::string stringValue = v.getString();
      
      // We need to handle the conversion ourselves to be able to get both
      // UTF8 encoding as well as explicit control over the length of the string
      // due to the possibility of null characters being part of the data
      CFStringRef cfString = CFStringCreateWithBytesNoCopy(NULL, (UInt8*)stringValue.data(),
                                                           stringValue.length(), kCFStringEncodingUTF8,
                                                           false, kCFAllocatorNull);
      JSStringRef stringRef = JSStringCreateWithCFString(cfString);
      JSValueRef toReturn = JSValueMakeString(contextRef, stringRef);
      JSStringRelease(stringRef);
      CFRelease(cfString);
      return toReturn;
    }
      
    case Value::JAVA_OBJECT:
      unsigned javaId = v.getJavaObjectId();
      JSObjectRef ref;
      
      pthread_mutex_lock(&javaObjectsLock);
      i = javaObjectsById.find(javaId);
      
      /*
       * It's possible that we've already finalized the JsObjectRef that
       * represented the object with the given id.  If so, we must remove it
       * from the list of finalized object ids to avoid prematurely freeing
       * the object on the server.
       */
      javaObjectsToFree.erase(javaId);
      
      if (i == javaObjectsById.end()) {
        /*
         * We don't call JSValueProtect so that the JavaObject peer can be
         * garbage-collected during the lifetime of the program.  Object
         * identity is maintained as long as the object hasn't been finalized.
         * If it had been finalized, then there wouldn't be an object to use
         * as a basis for identity comparison.
         *
         * NB: The act of creating the wrapper may trigger a GC.
         */
        ref = makeJavaWrapper(javaId);
        
        javaObjectsById[javaId] = ref;
        
      } else {
        ref = i->second;
      }
      pthread_mutex_unlock(&javaObjectsLock);
      
      
      return ref;
      
      case Value::JS_OBJECT:
      int jsId = v.getJsObjectId();
      
      i = jsObjectsById.find(jsId);
      if (i == jsObjectsById.end()) {
        char errMsg[50];
        snprintf(errMsg, sizeof(errMsg), "Missing JsObject with id %i", jsId);
        return makeException(errMsg);
        
      } else {
        return i->second;
      }
      
      case Value::UNDEFINED:
      return JSValueMakeUndefined(contextRef);
      
      default:
      char message[50];
      snprintf(message, sizeof(message), "Could not convert %s", v.toString().c_str());
      initiateAutodestructSequence(__PRETTY_FUNCTION__, message);
      return makeException(message);
  }
}

bool WebScriptSessionHandler::makeValue(Value& ret, JSValueRef v) {
  JSValueRef localException = NULL;
  
  if (JSValueIsNull(contextRef, v)) {
    ret.setNull();
    
  } else if (JSValueIsUndefined(contextRef, v)) {
    ret.setUndefined();
    
  } else if (JSValueIsBoolean(contextRef, v)) {
    ret.setBoolean(JSValueToBoolean(contextRef, v));
    
  } else if (JSValueIsNumber(contextRef, v)) {
    double d = JSValueToNumber(contextRef, v, &localException);
    int i = round(d);
    if (i == d) {
      ret.setInt(i);
    } else {
      ret.setDouble(d);
    }
    
  } else if (JSValueIsString(contextRef, v) ||
             JSValueIsInstanceOfConstructor(contextRef, v, stringConstructor, &localException)) {
    return makeValueFromString(ret, v);
    
  } else if (JSValueIsObjectOfClass(contextRef, v, javaObjectWrapperClass)) {
    // It's one of our Java object proxies
    JSObjectRef objectRef = JSValueToObject(contextRef, v, &localException);
    
    if (!localException) {
      TrackingDataRef tracker = (TrackingDataRef) JSObjectGetPrivate(objectRef);
      int objId = tracker->getObjectId();
      ret.setJavaObject(objId);
      Debug::log(Debug::Spam) << "Made a Java object Value " << objId << Debug::flush;
    }
    
  } else if (JSValueIsObject(contextRef, v)) {
    JSObjectRef objectRef = JSValueToObject(contextRef, v, &localException);
    if (!localException) {
      /*
       * Then this is just a plain-old JavaScript Object.  Because JSCore
       * doesn't retain private data for objects derived from the built-in
       * Object type, we'll simply revert to using a pair of maps to provide
       * a 1:1 mapping of JSObjectRefs and ints.
       */
      std::map<JSObjectRef, int>::iterator i = jsIdsByObject.find(objectRef);
      if (i != jsIdsByObject.end()) {
        // We've seen the object before
        ret.setJsObjectId(i->second);
      } else {
        // Allocate a new id
        int objId = ++jsObjectId;
        JSValueProtect(contextRef, objectRef);
        
        jsObjectsById[objId] = objectRef;
        jsIdsByObject[objectRef] = objId;
        
        ret.setJsObjectId(objId);
        Debug::log(Debug::Spam) << "Made JS Value " << objId << Debug::flush;
      }
    }
  } else {
    Debug::log(Debug::Error) << "Unhandled JSValueRef -> Value conversion in plugin" << Debug::flush;
    ret.setString("Unhandled JSValueRef -> Value conversion in plugin");
  }
  
  if (localException) {
    makeValue(ret, localException);
    return true;
  } else {
    return false;
  }
}

bool WebScriptSessionHandler::makeValueFromString(Value& ret, JSValueRef value) {
  JSValueRef localException = NULL;
  
  JSStringRef jsString = JSValueToStringCopy(contextRef, value, &localException);
  if (localException) {
    makeValue(ret, localException);
    return true;
  }
  
  CFStringRef cfString = JSStringCopyCFString(NULL, jsString);
  JSStringRelease(jsString);
  
  CFIndex cfLength = CFStringGetLength(cfString);
  CFIndex maxLength = CFStringGetMaximumSizeForEncoding(cfLength, kCFStringEncodingUTF8);
  scoped_array<char> utf8(new char[maxLength]);
  
  CFIndex numBytes;
  CFStringGetBytes(cfString, CFRangeMake(0, cfLength), kCFStringEncodingUTF8,
                   0, false, (UInt8*) utf8.get(), maxLength, &numBytes);    
  CFRelease(cfString);
  
  ret.setString(utf8.get(), numBytes);
  Debug::log(Debug::Spam) << "Made a string Value " << ret.getString() << Debug::flush;
  return false;
}
