/*
 * 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::fatalError(HostChannel& channel,
    const std::string& messsage) {
  // TODO: better way of reporting error?
  Debug::log(Debug::Error) << "Fatal error: " << message << Debug::flush;
}

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;
}
