Skip to content

Commit

Permalink
added blobs back. initial changes. doesn't yet compile
Browse files Browse the repository at this point in the history
  • Loading branch information
ekkis committed Apr 15, 2024
1 parent 5dd607c commit 44eb48a
Show file tree
Hide file tree
Showing 21 changed files with 1,261 additions and 12 deletions.
Binary file not shown.
746 changes: 746 additions & 0 deletions bridge/CMakeFiles/mercuryjs.dir/foundation/native_string.cc.o.d

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions bridge/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,9 @@ if ($ENV{MERCURYJS_ENGINE} MATCHES "quickjs")
core/dart_isolate_context.cc
core/dart_context_data.cc
core/executing_context_data.cc
core/fileapi/blob.cc
core/fileapi/blob_part.cc
core/fileapi/blob_property_bag.cc
core/module/console.cc
core/module/timer/timer.cc
core/module/timer/timer_coordinator.cc
Expand Down Expand Up @@ -269,6 +272,7 @@ if ($ENV{MERCURYJS_ENGINE} MATCHES "quickjs")
out/qjs_module_manager.cc
out/qjs_global_or_worker_scope.cc
out/qjs_global.cc
out/qjs_blob.cc
out/qjs_event.cc
out/qjs_add_event_listener_options.cc
out/qjs_event_listener_options.cc
Expand Down
2 changes: 1 addition & 1 deletion bridge/bindings/qjs/wrapper_type_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class TouchList;
// Define all built-in wrapper class id.
enum {
JS_CLASS_GC_TRACKER = JS_CLASS_INIT_COUNT + 1,
JS_CLASS_BLOB,
JS_CLASS_EVENT,
JS_CLASS_ERROR_EVENT,
JS_CLASS_MESSAGE_EVENT,
Expand All @@ -26,7 +27,6 @@ enum {
JS_CLASS_PROMISE_REJECTION_EVENT,
JS_CLASS_EVENT_TARGET,
JS_CLASS_GLOBAL,

JS_CLASS_CUSTOM_CLASS_INIT_COUNT /* last entry for predefined classes */
};

Expand Down
2 changes: 1 addition & 1 deletion bridge/core/fileapi/array_buffer_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ struct ArrayBufferData {
int32_t length;
};

} // namespace webf
} // namespace mercury

#endif // BRIDGE_CORE_FILEAPI_ARRAY_BUFFER_DATA_H_
182 changes: 182 additions & 0 deletions bridge/core/fileapi/blob.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
/*
* Copyright (C) 2019-2022 The Kraken authors. All rights reserved.
* Copyright (C) 2022-present The WebF authors. All rights reserved.
*/
#include "blob.h"
#include <modp_b64/modp_b64.h>
#include <string>
#include "bindings/qjs/script_promise_resolver.h"
#include "built_in_string.h"
#include "core/executing_context.h"

namespace mercury {

class BlobReaderClient {
public:
enum ReadType { kReadAsText, kReadAsArrayBuffer, kReadAsBase64 };

BlobReaderClient(ExecutingContext* context,
Blob* blob,
std::shared_ptr<ScriptPromiseResolver> resolver,
ReadType read_type)
: context_(context), blob_(blob), resolver_(std::move(resolver)), read_type_(read_type) {
Start();
};

void Start();
void DidFinishLoading();

private:
ExecutingContext* context_;
Blob* blob_;
std::shared_ptr<ScriptPromiseResolver> resolver_;
ReadType read_type_;
};

void BlobReaderClient::Start() {
DidFinishLoading();
}

void BlobReaderClient::DidFinishLoading() {
if (read_type_ == ReadType::kReadAsText) {
resolver_->Resolve<std::string>(blob_->StringResult());
} else if (read_type_ == ReadType::kReadAsArrayBuffer) {
resolver_->Resolve<ArrayBufferData>(blob_->ArrayBufferResult());
} else if (read_type_ == ReadType::kReadAsBase64) {
resolver_->Resolve<std::string>(blob_->Base64Result());
}
delete this;
}

Blob* Blob::Create(ExecutingContext* context, ExceptionState& exception_state) {
return MakeGarbageCollected<Blob>(context->ctx());
}

Blob* Blob::Create(ExecutingContext* context) {
return MakeGarbageCollected<Blob>(context->ctx());
}

Blob* Blob::Create(ExecutingContext* context,
std::vector<std::shared_ptr<BlobPart>>& data,
ExceptionState& exception_state) {
return MakeGarbageCollected<Blob>(context->ctx(), data);
}

Blob* Blob::Create(ExecutingContext* context,
std::vector<std::shared_ptr<BlobPart>>& data,
std::shared_ptr<BlobPropertyBag> property,
ExceptionState& exception_state) {
return MakeGarbageCollected<Blob>(context->ctx(), data, property);
}

int32_t Blob::size() {
return _data.size();
}

uint8_t* Blob::bytes() {
return _data.data();
}

void Blob::Trace(GCVisitor* visitor) const {}

Blob* Blob::slice(ExceptionState& exception_state) {
return slice(0, _data.size(), exception_state);
}
Blob* Blob::slice(int64_t start, ExceptionState& exception_state) {
return slice(start, _data.size(), exception_state);
}
Blob* Blob::slice(int64_t start, int64_t end, ExceptionState& exception_state) {
return slice(start, end, AtomicString::Empty(), exception_state);
}
Blob* Blob::slice(int64_t start, int64_t end, const AtomicString& content_type, ExceptionState& exception_state) {
auto* newBlob = MakeGarbageCollected<Blob>(ctx());
std::vector<uint8_t> newData;
newData.reserve(_data.size() - (end - start));
newData.insert(newData.begin(), _data.begin() + start, _data.end() - (_data.size() - end));
newBlob->_data = newData;
newBlob->mime_type_ = content_type != built_in_string::kempty_string ? content_type.ToStdString(ctx()) : mime_type_;
return newBlob;
}

std::string Blob::StringResult() {
return std::string(bytes(), bytes() + size());
}

std::string Blob::Base64Result() {
size_t encode_len = modp_b64_encode_data_len(size());
std::string buffer;
buffer.resize(encode_len);

const size_t output_size =
modp_b64_encode_data(reinterpret_cast<char*>(buffer.data()), reinterpret_cast<const char*>(bytes()), size());
assert(output_size == encode_len);

return "data:" + mime_type_ + ";base64," + buffer;
}

ArrayBufferData Blob::ArrayBufferResult() {
return ArrayBufferData{bytes(), size()};
}

std::string Blob::type() {
return mime_type_;
}

void Blob::SetMineType(const std::string& mine_type) {
mime_type_ = mine_type;
}

ScriptPromise Blob::arrayBuffer(ExceptionState& exception_state) {
auto resolver = ScriptPromiseResolver::Create(GetExecutingContext());
new BlobReaderClient(GetExecutingContext(), this, resolver, BlobReaderClient::ReadType::kReadAsArrayBuffer);
return resolver->Promise();
}

ScriptPromise Blob::text(ExceptionState& exception_state) {
auto resolver = ScriptPromiseResolver::Create(GetExecutingContext());
new BlobReaderClient(GetExecutingContext(), this, resolver, BlobReaderClient::ReadType::kReadAsText);
return resolver->Promise();
}

ScriptPromise Blob::base64(ExceptionState& exception_state) {
auto resolver = ScriptPromiseResolver::Create(GetExecutingContext());
new BlobReaderClient(GetExecutingContext(), this, resolver, BlobReaderClient::ReadType::kReadAsBase64);
return resolver->Promise();
}

void Blob::PopulateBlobData(const std::vector<std::shared_ptr<BlobPart>>& data) {
for (auto& item : data) {
switch (item->GetContentType()) {
case BlobPart::ContentType::kString: {
AppendText(item->GetString());
break;
}
case BlobPart::ContentType::kArrayBuffer:
case BlobPart::ContentType::kArrayBufferView: {
uint32_t length;
uint8_t* buffer = item->GetBytes(&length);
AppendBytes(buffer, length);
break;
}
case BlobPart::ContentType::kBlob: {
AppendBytes(item->GetBlob()->bytes(), item->GetBlob()->size());
break;
}
}
}
}

void Blob::AppendText(const std::string& string) {
std::vector<uint8_t> strArr(string.begin(), string.end());
_data.reserve(_data.size() + strArr.size());
_data.insert(_data.end(), strArr.begin(), strArr.end());
}

void Blob::AppendBytes(uint8_t* buffer, uint32_t length) {
_data.reserve(_data.size() + length);
for (size_t i = 0; i < length; i++) {
_data.emplace_back(buffer[i]);
}
}

} // namespace mercury
9 changes: 9 additions & 0 deletions bridge/core/fileapi/blob.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
interface Blob {
readonly size: number;
readonly type: string;
arrayBuffer(): Promise<ArrayBuffer>;
slice(start?: int64, end?: int64, contentType?: string): Blob;
text(): Promise<string>;
base64(): Promise<string>;
new(blobParts?: BlobPart[], options?: BlobPropertyBag): Blob;
}
81 changes: 81 additions & 0 deletions bridge/core/fileapi/blob.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* Copyright (C) 2019-2022 The Kraken authors. All rights reserved.
* Copyright (C) 2022-present The WebF authors. All rights reserved.
*/
#ifndef BRIDGE_BLOB_H
#define BRIDGE_BLOB_H

#include <string>
#include <vector>
#include "array_buffer_data.h"
#include "bindings/qjs/macros.h"
#include "bindings/qjs/script_promise.h"
#include "bindings/qjs/script_wrappable.h"
#include "blob_part.h"
#include "blob_property_bag.h"

namespace mercury {

class Blob : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();

public:
using ImplType = Blob*;
static Blob* Create(ExecutingContext* context, ExceptionState& exception_state);
static Blob* Create(ExecutingContext* context);
static Blob* Create(ExecutingContext* context,
std::vector<std::shared_ptr<BlobPart>>& data,
ExceptionState& exception_state);
static Blob* Create(ExecutingContext* context,
std::vector<std::shared_ptr<BlobPart>>& data,
std::shared_ptr<BlobPropertyBag> property,
ExceptionState& exception_state);

Blob() = delete;
explicit Blob(JSContext* ctx) : ScriptWrappable(ctx){};
explicit Blob(JSContext* ctx, const std::vector<std::shared_ptr<BlobPart>>& data) : ScriptWrappable(ctx) {
PopulateBlobData(data);
};
explicit Blob(JSContext* ctx,
std::vector<std::shared_ptr<BlobPart>>& data,
std::shared_ptr<BlobPropertyBag>& property)
: mime_type_(property->type()), ScriptWrappable(ctx) {
PopulateBlobData(data);
};

void AppendText(const std::string& string);
void AppendBytes(uint8_t* buffer, uint32_t length);

/// get an pointer of bytes data from JSBlob
uint8_t* bytes();
/// get bytes data's length
int32_t size();
std::string type();
void SetMineType(const std::string& mine_type);

ScriptPromise arrayBuffer(ExceptionState& exception_state);
ScriptPromise text(ExceptionState& exception_state);
ScriptPromise base64(ExceptionState& exception_state);

Blob* slice(ExceptionState& exception_state);
Blob* slice(int64_t start, ExceptionState& exception_state);
Blob* slice(int64_t start, int64_t end, ExceptionState& exception_state);
Blob* slice(int64_t start, int64_t end, const AtomicString& content_type, ExceptionState& exception_state);

std::string StringResult();
std::string Base64Result();
ArrayBufferData ArrayBufferResult();

void Trace(GCVisitor* visitor) const override;

protected:
void PopulateBlobData(const std::vector<std::shared_ptr<BlobPart>>& data);

private:
std::string mime_type_;
std::vector<uint8_t> _data;
};

} // namespace mercury

#endif // BRIDGE_BLOB_H
Loading

0 comments on commit 44eb48a

Please sign in to comment.