nsresult
nsDOMMultipartFile::InitBlob(JSContext* aCx,
                             uint32_t aArgc,
                             JS::Value* aArgv,
                             UnwrapFuncPtr aUnwrapFunc)
{
  bool nativeEOL = false;
  if (aArgc > 1) {
    BlobPropertyBag d;
    if (!d.Init(aCx, JS::Handle<JS::Value>::fromMarkedLocation(&aArgv[1]))) {
      return NS_ERROR_TYPE_ERR;
    }
    mContentType = d.mType;
    nativeEOL = d.mEndings == EndingTypes::Native;
  }

  if (aArgc > 0) {
    return ParseBlobArrayArgument(aCx, aArgv[0], nativeEOL, aUnwrapFunc);
  }

  return NS_OK;
}
nsresult
DOMMultipartFileImpl::InitFile(JSContext* aCx,
                               uint32_t aArgc,
                               JS::Value* aArgv)
{
  NS_ASSERTION(!mImmutable, "Something went wrong ...");
  NS_ENSURE_TRUE(!mImmutable, NS_ERROR_UNEXPECTED);

  if (aArgc < 2) {
    return NS_ERROR_TYPE_ERR;
  }

  // File name
  JSString* str = JS::ToString(aCx, JS::Handle<JS::Value>::fromMarkedLocation(&aArgv[1]));
  NS_ENSURE_TRUE(str, NS_ERROR_XPC_BAD_CONVERT_JS);

  nsAutoJSString xpcomStr;
  if (!xpcomStr.init(aCx, str)) {
    return NS_ERROR_XPC_BAD_CONVERT_JS;
  }

  mName = xpcomStr;

  // Optional params
  bool nativeEOL = false;
  if (aArgc > 2) {
    BlobPropertyBag d;
    if (!d.Init(aCx, JS::Handle<JS::Value>::fromMarkedLocation(&aArgv[2]))) {
      return NS_ERROR_TYPE_ERR;
    }
    mContentType = d.mType;
    nativeEOL = d.mEndings == EndingTypes::Native;
  }

  return ParseBlobArrayArgument(aCx, aArgv[0], nativeEOL, GetXPConnectNative);
}
nsresult
nsDOMMultipartFile::InitInternal(JSContext* aCx,
                                 uint32_t aArgc,
                                 jsval* aArgv,
                                 UnwrapFuncPtr aUnwrapFunc)
{
  bool nativeEOL = false;
  if (aArgc > 1) {
    if (NS_IsMainThread()) {
      BlobPropertyBag d;
      if (!d.Init(aCx, nullptr, aArgv[1])) {
        return NS_ERROR_TYPE_ERR;
      }
      mContentType = d.type;
      nativeEOL = d.endings == EndingTypesValues::Native;
    } else {
      BlobPropertyBagWorkers d;
      if (!d.Init(aCx, nullptr, aArgv[1])) {
        return NS_ERROR_TYPE_ERR;
      }
      mContentType = d.type;
      nativeEOL = d.endings == EndingTypesValues::Native;
    }
  }

  if (aArgc > 0) {
    if (!aArgv[0].isObject()) {
      return NS_ERROR_TYPE_ERR; // We're not interested
    }

    JSObject& obj = aArgv[0].toObject();
    if (!JS_IsArrayObject(aCx, &obj)) {
      return NS_ERROR_TYPE_ERR; // We're not interested
    }

    BlobSet blobSet;

    uint32_t length;
    JS_ALWAYS_TRUE(JS_GetArrayLength(aCx, &obj, &length));
    for (uint32_t i = 0; i < length; ++i) {
      jsval element;
      if (!JS_GetElement(aCx, &obj, i, &element))
        return NS_ERROR_TYPE_ERR;

      if (element.isObject()) {
        JSObject& obj = element.toObject();
        nsCOMPtr<nsIDOMBlob> blob = aUnwrapFunc(aCx, &obj);
        if (blob) {
          // Flatten so that multipart blobs will never nest
          nsDOMFileBase* file = static_cast<nsDOMFileBase*>(
              static_cast<nsIDOMBlob*>(blob));
          const nsTArray<nsCOMPtr<nsIDOMBlob> >*
              subBlobs = file->GetSubBlobs();
          if (subBlobs) {
            blobSet.AppendBlobs(*subBlobs);
          } else {
            blobSet.AppendBlob(blob);
          }
          continue;
        }
        if (JS_IsArrayBufferViewObject(&obj, aCx)) {
          blobSet.AppendVoidPtr(JS_GetArrayBufferViewData(&obj, aCx),
                                JS_GetArrayBufferViewByteLength(&obj, aCx));
          continue;
        }
        if (JS_IsArrayBufferObject(&obj, aCx)) {
          blobSet.AppendArrayBuffer(&obj, aCx);
          continue;
        }
        // neither Blob nor ArrayBuffer(View)
      } else if (element.isString()) {
        blobSet.AppendString(element.toString(), nativeEOL, aCx);
        continue;
      }
      // coerce it to a string
      JSString* str = JS_ValueToString(aCx, element);
      NS_ENSURE_TRUE(str, NS_ERROR_TYPE_ERR);
      blobSet.AppendString(str, nativeEOL, aCx);
    }

    mBlobs = blobSet.GetBlobs();
  }

  return NS_OK;
}