mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-06-05 21:39:12 +02:00
Add support for V8 ArrayBuffers (issue #244)
This commit is contained in:
committed by
Marshall Greenblatt
parent
bb28b85bdd
commit
4315f3b724
@ -304,6 +304,74 @@ class V8TrackString : public CefTrackNode {
|
||||
std::string string_;
|
||||
};
|
||||
|
||||
class V8TrackArrayBuffer : public CefTrackNode {
|
||||
public:
|
||||
explicit V8TrackArrayBuffer(
|
||||
v8::Isolate* isolate,
|
||||
void* buffer,
|
||||
CefRefPtr<CefV8ArrayBufferReleaseCallback> release_callback)
|
||||
: isolate_(isolate),
|
||||
buffer_(buffer),
|
||||
release_callback_(release_callback) {
|
||||
DCHECK(isolate_);
|
||||
}
|
||||
|
||||
~V8TrackArrayBuffer() {
|
||||
if (buffer_ != nullptr) {
|
||||
release_callback_->ReleaseBuffer(buffer_);
|
||||
}
|
||||
isolate_->AdjustAmountOfExternalAllocatedMemory(
|
||||
-static_cast<int>(sizeof(V8TrackArrayBuffer)));
|
||||
}
|
||||
|
||||
CefRefPtr<CefV8ArrayBufferReleaseCallback> GetReleaseCallback() {
|
||||
return release_callback_;
|
||||
}
|
||||
|
||||
void Neuter() { buffer_ = nullptr; }
|
||||
|
||||
// Retrieve the track object for the specified V8 object.
|
||||
static V8TrackArrayBuffer* Unwrap(v8::Local<v8::Context> context,
|
||||
v8::Local<v8::Object> object) {
|
||||
v8::Local<v8::Value> value;
|
||||
if (GetPrivate(context, object, kCefTrackObject, &value))
|
||||
return static_cast<V8TrackArrayBuffer*>(
|
||||
v8::External::Cast(*value)->Value());
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Attach this track object to the specified V8 object.
|
||||
void AttachTo(v8::Local<v8::Context> context,
|
||||
v8::Local<v8::ArrayBuffer> arrayBuffer) {
|
||||
isolate_->AdjustAmountOfExternalAllocatedMemory(
|
||||
static_cast<int>(sizeof(V8TrackArrayBuffer)));
|
||||
|
||||
SetPrivate(context, arrayBuffer, kCefTrackObject,
|
||||
v8::External::New(isolate_, this));
|
||||
|
||||
handle_.Reset(isolate_, arrayBuffer);
|
||||
handle_.SetWeak(this, FirstWeakCallback, v8::WeakCallbackType::kParameter);
|
||||
handle_.MarkIndependent();
|
||||
}
|
||||
|
||||
private:
|
||||
static void FirstWeakCallback(
|
||||
const v8::WeakCallbackInfo<V8TrackArrayBuffer>& data) {
|
||||
V8TrackArrayBuffer* wrapper = data.GetParameter();
|
||||
if (wrapper->buffer_ != nullptr) {
|
||||
wrapper->release_callback_->ReleaseBuffer(wrapper->buffer_);
|
||||
wrapper->buffer_ = nullptr;
|
||||
}
|
||||
wrapper->handle_.Reset();
|
||||
}
|
||||
|
||||
v8::Isolate* isolate_;
|
||||
void* buffer_;
|
||||
CefRefPtr<CefV8ArrayBufferReleaseCallback> release_callback_;
|
||||
v8::Persistent<v8::ArrayBuffer> handle_;
|
||||
};
|
||||
|
||||
// Object wrapped in a v8::External and passed as the Data argument to
|
||||
// v8::FunctionTemplate::New.
|
||||
class V8FunctionData {
|
||||
@ -1311,6 +1379,35 @@ CefRefPtr<CefV8Value> CefV8Value::CreateArray(int length) {
|
||||
return impl.get();
|
||||
}
|
||||
|
||||
// static
|
||||
CefRefPtr<CefV8Value> CefV8Value::CreateArrayBuffer(
|
||||
void* buffer,
|
||||
size_t length,
|
||||
CefRefPtr<CefV8ArrayBufferReleaseCallback> release_callback) {
|
||||
CEF_V8_REQUIRE_ISOLATE_RETURN(NULL);
|
||||
|
||||
v8::Isolate* isolate = GetIsolateManager()->isolate();
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
v8::Local<v8::Context> context = isolate->GetCurrentContext();
|
||||
if (context.IsEmpty()) {
|
||||
NOTREACHED() << "not currently in a V8 context";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Create a tracker object that will cause the user data reference to be
|
||||
// released when the V8 object is destroyed.
|
||||
V8TrackArrayBuffer* tracker =
|
||||
new V8TrackArrayBuffer(isolate, buffer, release_callback);
|
||||
v8::Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, buffer, length);
|
||||
|
||||
// Attach the tracker object.
|
||||
tracker->AttachTo(context, ab);
|
||||
|
||||
CefRefPtr<CefV8ValueImpl> impl = new CefV8ValueImpl(isolate);
|
||||
impl->InitObject(ab, tracker);
|
||||
return impl.get();
|
||||
}
|
||||
|
||||
// static
|
||||
CefRefPtr<CefV8Value> CefV8Value::CreateFunction(
|
||||
const CefString& name,
|
||||
@ -1571,6 +1668,16 @@ bool CefV8ValueImpl::IsArray() {
|
||||
}
|
||||
}
|
||||
|
||||
bool CefV8ValueImpl::IsArrayBuffer() {
|
||||
CEF_V8_REQUIRE_MLT_RETURN(false);
|
||||
if (type_ == TYPE_OBJECT) {
|
||||
v8::HandleScope handle_scope(handle_->isolate());
|
||||
return handle_->GetNewV8Handle(false)->IsArrayBuffer();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool CefV8ValueImpl::IsFunction() {
|
||||
CEF_V8_REQUIRE_MLT_RETURN(false);
|
||||
if (type_ == TYPE_OBJECT) {
|
||||
@ -2091,6 +2198,60 @@ int CefV8ValueImpl::GetArrayLength() {
|
||||
return arr->Length();
|
||||
}
|
||||
|
||||
CefRefPtr<CefV8ArrayBufferReleaseCallback>
|
||||
CefV8ValueImpl::GetArrayBufferReleaseCallback() {
|
||||
CEF_V8_REQUIRE_OBJECT_RETURN(0);
|
||||
|
||||
v8::Isolate* isolate = handle_->isolate();
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
v8::Local<v8::Context> context = isolate->GetCurrentContext();
|
||||
if (context.IsEmpty()) {
|
||||
NOTREACHED() << "not currently in a V8 context";
|
||||
return NULL;
|
||||
}
|
||||
v8::Local<v8::Value> value = handle_->GetNewV8Handle(false);
|
||||
if (!value->IsArrayBuffer()) {
|
||||
NOTREACHED() << "V8 value is not an array buffer";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
v8::Local<v8::Object> obj = value->ToObject();
|
||||
|
||||
V8TrackArrayBuffer* tracker = V8TrackArrayBuffer::Unwrap(context, obj);
|
||||
if (tracker)
|
||||
return tracker->GetReleaseCallback();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool CefV8ValueImpl::NeuterArrayBuffer() {
|
||||
CEF_V8_REQUIRE_OBJECT_RETURN(0);
|
||||
|
||||
v8::Isolate* isolate = handle_->isolate();
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
v8::Local<v8::Context> context = isolate->GetCurrentContext();
|
||||
if (context.IsEmpty()) {
|
||||
NOTREACHED() << "not currently in a V8 context";
|
||||
return false;
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> value = handle_->GetNewV8Handle(false);
|
||||
if (!value->IsArrayBuffer()) {
|
||||
NOTREACHED() << "V8 value is not an array buffer";
|
||||
return false;
|
||||
}
|
||||
v8::Local<v8::Object> obj = value->ToObject();
|
||||
v8::Local<v8::ArrayBuffer> arr = v8::Local<v8::ArrayBuffer>::Cast(obj);
|
||||
if (!arr->IsNeuterable()) {
|
||||
return false;
|
||||
}
|
||||
arr->Neuter();
|
||||
V8TrackArrayBuffer* tracker = V8TrackArrayBuffer::Unwrap(context, obj);
|
||||
tracker->Neuter();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
CefString CefV8ValueImpl::GetFunctionName() {
|
||||
CefString rv;
|
||||
CEF_V8_REQUIRE_OBJECT_RETURN(rv);
|
||||
|
@ -227,6 +227,7 @@ class CefV8ValueImpl : public CefV8Value {
|
||||
bool IsString() override;
|
||||
bool IsObject() override;
|
||||
bool IsArray() override;
|
||||
bool IsArrayBuffer() override;
|
||||
bool IsFunction() override;
|
||||
bool IsSame(CefRefPtr<CefV8Value> value) override;
|
||||
bool GetBoolValue() override;
|
||||
@ -260,6 +261,9 @@ class CefV8ValueImpl : public CefV8Value {
|
||||
int GetExternallyAllocatedMemory() override;
|
||||
int AdjustExternallyAllocatedMemory(int change_in_bytes) override;
|
||||
int GetArrayLength() override;
|
||||
CefRefPtr<CefV8ArrayBufferReleaseCallback> GetArrayBufferReleaseCallback()
|
||||
override;
|
||||
bool NeuterArrayBuffer() override;
|
||||
CefString GetFunctionName() override;
|
||||
CefRefPtr<CefV8Handler> GetFunctionHandler() override;
|
||||
CefRefPtr<CefV8Value> ExecuteFunction(
|
||||
|
Reference in New Issue
Block a user