/* [implicit_jscontext] void writeToContext2D (in nsIDOMCanvasRenderingContext2D ctx, in jsval source, in long width, in long height); */
NS_IMETHODIMP dpoCContext::WriteToContext2D(nsIDOMCanvasRenderingContext2D *ctx, const JS::Value & source, PRInt32 width, PRInt32 height, JSContext* cx)
{
#ifdef DIRECT_WRITE
	JSObject *srcArray;
	nsresult result;

	result = ExtractArray(source, &srcArray, cx);
	if (NS_FAILED(result)) {
		return result;
	}

	uint32_t size = JS_GetTypedArrayLength(srcArray);

	if (size != width*height*4)
		return NS_ERROR_INVALID_ARG;

    if (JS_IsFloat32Array(srcArray)) {
		unsigned char *data = (unsigned char *) nsMemory::Alloc(size);
		float *src = JS_GetFloat32ArrayData(srcArray);
		for (int i = 0; i < size; i++) {
			float val = src[i];
			data[i] = val > 0 ? (val < 255 ? ((int) val) : 255) : 0;
		}
		ctx->PutImageData_explicit(0, 0, width, height, data, size, false, 0, 0, 0, 0);
        nsMemory::Free(data);
	} else if (JS_IsFloat64Array(srcArray)) {
		unsigned char *data = (unsigned char *) nsMemory::Alloc(size);
		double *src = JS_GetFloat64ArrayData(srcArray);
		for (int i = 0; i < size; i++) {
			double val = src[i];
			data[i] = val > 0 ? (val < 255 ? ((int) val) : 255) : 0;
		}
		ctx->PutImageData_explicit(0, 0, width, height, data, size, false, 0, 0, 0, 0);
        nsMemory::Free(data);
	} else if(JS_IsUint8ClampedArray(srcArray)) {
		uint8_t *src = JS_GetUint8ClampedArrayData(srcArray);
		ctx->PutImageData_explicit(0, 0, width, height, src, size, false, 0, 0, 0, 0);
	} else if(JS_IsUint8Array(srcArray)) {
		return NS_ERROR_INVALID_ARG;
	} else {
		return NS_ERROR_NOT_IMPLEMENTED;
	}

	return NS_OK;
#else /* DIRECT_WRITE */
	return NS_ERROR_NOT_IMPLEMENTED;
#endif /* DIRECT_WRITE */
}
NS_IMETHODIMP
TCPSocketParent::SendCallback(const nsAString& aType, const JS::Value& aDataVal,
                              const nsAString& aReadyState, uint32_t aBuffered,
                              JSContext* aCx)
{
  if (!mIPCOpen) {
    NS_WARNING("Dropping callback due to no IPC connection");
    return NS_OK;
  }

  CallbackData data;
  if (aDataVal.isString()) {
    JSString* jsstr = aDataVal.toString();
    nsDependentJSString str;
    if (!str.init(aCx, jsstr)) {
      FireInteralError(this, __LINE__);
      return NS_ERROR_OUT_OF_MEMORY;
    }
    data = str;

  } else if (aDataVal.isUndefined() || aDataVal.isNull()) {
    data = mozilla::void_t();

  } else if (aDataVal.isObject()) {
    JSObject* obj = &aDataVal.toObject();
    if (JS_IsTypedArrayObject(obj)) {
      NS_ENSURE_TRUE(JS_IsUint8Array(obj), NS_ERROR_FAILURE);
      uint32_t nbytes = JS_GetTypedArrayByteLength(obj);
      uint8_t* buffer = JS_GetUint8ArrayData(obj);
      if (!buffer) {
        FireInteralError(this, __LINE__);
        return NS_ERROR_OUT_OF_MEMORY;
      }
      FallibleTArray<uint8_t> fallibleArr;
      if (!fallibleArr.InsertElementsAt(0, buffer, nbytes)) {
        FireInteralError(this, __LINE__);
        return NS_ERROR_OUT_OF_MEMORY;
      }
      InfallibleTArray<uint8_t> arr;
      arr.SwapElements(fallibleArr);
      data = SendableData(arr);

    } else {
      nsDependentJSString message, filename;
      uint32_t lineNumber = 0;
      uint32_t columnNumber = 0;

      jsval val;
      if (!JS_GetProperty(aCx, obj, "message", &val)) {
        NS_ERROR("No message property on supposed error object");
      } else if (JSVAL_IS_STRING(val)) {
        if (!message.init(aCx, JSVAL_TO_STRING(val))) {
          NS_WARNING("couldn't initialize string");
        }
      }

      if (!JS_GetProperty(aCx, obj, "fileName", &val)) {
        NS_ERROR("No fileName property on supposed error object");
      } else if (JSVAL_IS_STRING(val)) {
        if (!filename.init(aCx, JSVAL_TO_STRING(val))) {
          NS_WARNING("couldn't initialize string");
        }
      }

      if (!JS_GetProperty(aCx, obj, "lineNumber", &val)) {
        NS_ERROR("No lineNumber property on supposed error object");
      } else if (JSVAL_IS_INT(val)) {
        lineNumber = JSVAL_TO_INT(val);
      }

      if (!JS_GetProperty(aCx, obj, "columnNumber", &val)) {
        NS_ERROR("No columnNumber property on supposed error object");
      } else if (JSVAL_IS_INT(val)) {
        columnNumber = JSVAL_TO_INT(val);
      }

      data = JSError(message, filename, lineNumber, columnNumber);
    }
  } else {
    NS_ERROR("Unexpected JS value encountered");
    FireInteralError(this, __LINE__);
    return NS_ERROR_FAILURE;
  }
  mozilla::unused <<
      PTCPSocketParent::SendCallback(nsString(aType), data,
                                     nsString(aReadyState), aBuffered);
  return NS_OK;
}