blob: 43ff82e3d6daffc4ed992db58c7d012f59f21589 [file] [log] [blame]
/*
* Copyright (C) 2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "JSFile.h"
#include "JSDOMBinding.h"
#include "JSDictionary.h"
#include "ScriptExecutionContext.h"
#include "WebKitBlobBuilder.h"
#include <runtime/Error.h>
#include <runtime/JSArray.h>
#include <runtime/JSArrayBuffer.h>
#include <runtime/JSArrayBufferView.h>
#include <wtf/Assertions.h>
#include <wtf/CurrentTime.h>
using namespace JSC;
namespace WebCore {
EncodedJSValue JSC_HOST_CALL constructJSFile(ExecState& exec)
{
VM& vm = exec.vm();
auto scope = DECLARE_THROW_SCOPE(vm);
auto* constructor = jsCast<DOMConstructorObject*>(exec.callee());
ASSERT(constructor);
ScriptExecutionContext* context = constructor->scriptExecutionContext();
if (!context)
return throwConstructorScriptExecutionContextUnavailableError(exec, scope, "File");
ASSERT(context->isDocument());
JSValue arg = exec.argument(0);
if (arg.isUndefinedOrNull())
return throwArgumentTypeError(exec, scope, 0, "fileBits", "File", nullptr, "sequence");
unsigned blobPartsLength = 0;
JSObject* blobParts = toJSSequence(exec, arg, blobPartsLength);
RETURN_IF_EXCEPTION(scope, encodedJSValue());
ASSERT(blobParts);
arg = exec.argument(1);
if (arg.isUndefined())
return throwArgumentTypeError(exec, scope, 1, "filename", "File", nullptr, "DOMString");
String filename = arg.toWTFString(&exec).replace('/', ':');
RETURN_IF_EXCEPTION(scope, encodedJSValue());
String normalizedType;
Optional<int64_t> lastModified;
arg = exec.argument(2);
if (!arg.isUndefinedOrNull()) {
JSObject* filePropertyBagObject = arg.getObject();
if (!filePropertyBagObject)
return throwArgumentTypeError(exec, scope, 2, "options", "File", nullptr, "FilePropertyBag");
// Create the dictionary wrapper from the initializer object.
JSDictionary dictionary(&exec, filePropertyBagObject);
// Attempt to get the type property.
String type;
dictionary.get("type", type);
RETURN_IF_EXCEPTION(scope, encodedJSValue());
normalizedType = Blob::normalizedContentType(type);
// Only try to parse the lastModified date if there was not an invalid type argument.
if (type.isEmpty() || !normalizedType.isEmpty()) {
dictionary.get("lastModified", lastModified);
RETURN_IF_EXCEPTION(scope, encodedJSValue());
}
}
if (!lastModified)
lastModified = currentTimeMS();
BlobBuilder blobBuilder;
for (unsigned i = 0; i < blobPartsLength; ++i) {
JSValue item = blobParts->get(&exec, i);
RETURN_IF_EXCEPTION(scope, encodedJSValue());
if (ArrayBuffer* arrayBuffer = toUnsharedArrayBuffer(item))
blobBuilder.append(arrayBuffer);
else if (RefPtr<ArrayBufferView> arrayBufferView = toUnsharedArrayBufferView(item))
blobBuilder.append(WTFMove(arrayBufferView));
else if (Blob* blob = JSBlob::toWrapped(item))
blobBuilder.append(blob);
else {
String string = item.toWTFString(&exec);
RETURN_IF_EXCEPTION(scope, encodedJSValue());
blobBuilder.append(string, ASCIILiteral("transparent"));
}
}
auto file = File::create(blobBuilder.finalize(), filename, normalizedType, lastModified.value());
return JSValue::encode(createWrapper<File>(constructor->globalObject(), WTFMove(file)));
}
} // namespace WebCore